Swift 4.2 中带有 JSON 数据的 Tableview

Posted

技术标签:

【中文标题】Swift 4.2 中带有 JSON 数据的 Tableview【英文标题】:Tableview with JSON Data in Swift 4.2 【发布时间】:2019-03-11 11:34:56 【问题描述】:

我是 Swift 的新手,我已经无能为力了,所以请善待我。

我正在构建一个应用程序,该应用程序通过发布特定 ID 并取回 JSON 数组来从 url 下载数据。 JSON 看起来像这样:

["group":"500","from":"2019-01-01","to":"2019-01-05",...]

它的组号为“group”,开始日期为“from”,结束日期为“to”。

我想让 Tableview 中显示的不同组也带有 FromTo-日期。我设法正确下载了数据,但在表格视图中显示它们失败了。

我的代码在下面。也许你们中的某个人可以找出我做错了什么。

当我运行项目时,我得到一个空表。

    import UIKit

   typealias Fahrten = [FahrtenElement]

struct FahrtenElement: Codable 
    let group: String?
    let from: String?
    let to: String?

    enum CodingKeys: String, CodingKey 
        case group = "group"
        case from = "from"
        case to = "to"
    


    class BookingsController: UITableViewController 

        var tableview: UITableView!
        var groups = [Fahrten]()


        // MARK: - Table view data source

        override func viewDidLoad() 
            super.viewDidLoad()
            downloadData()
        

        override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? 
            let label = UILabel()
            label.text = "Groups"
            label.backgroundColor = .yellow

            return label
        


        // Section
        override func numberOfSections(in tableView: UITableView) -> Int 
            return 1
        

        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
            return self.groups.count
        

        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            //lblname to set the title from response
            cell.textLabel?.text = "Group \(String(describing: groups[indexPath.row].group))"
            cell.detailTextLabel?.text = "From \(String(describing: groups[indexPath.row].from)) to \(String(describing: groups[indexPath.row].to))"
            return cell
        

        func downloadData() 
            let id = "..."

            let url = URL(string: "...")!

            // request url
            var request = URLRequest(url: url)

            // method to pass data POST - cause it is secured
            request.httpMethod = "POST"

            // body gonna be appended to url
            let body = "id=(\(id))"

            // append body to our request that gonna be sent
            request.httpBody = body.data(using: .utf8)

            URLSession.shared.dataTask(with: request)  (data, response, err) in



guard let data = data else  return 


            do 

               let groups = try JSONDecoder().decode(Fahrten.self, from: data)

                print(groups)                        
self.tableview.reloadData() // I get an crash here: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value                    
                 catch let jsonErr 
                    print("Error serializing json:", jsonErr)
                

                .resume()
        

【问题讨论】:

添加tableview.dataSource=true也取消注释这一行:self.tableview.reloadData()self.groups = [Fahrten]()之后 你为什么评论这个? // self.tableview.reloadData() 我在“self.tableview.reloadData()”处发生崩溃。“线程 1:致命错误:在展开可选值时意外发现 nil” 你的tableView是nil?也许?你只在 viewDidLoad 中调用 downloadData 吗?你如何初始化视图控制器? 尝试在这一行添加断点并单步执行代码。检查检查器中的值以检查 nil 【参考方案1】:

据我所见,您似乎正在清空数组而不是重新加载数据。

您应该将生成的组属性分配给self.groups,然后重新加载数据。

DispatchQueue.main.async 
    self.groups = groups // change here
    self.tableview.reloadData()

【讨论】:

当我重新加载数据时,我得到“线程 1:致命错误:在展开可选值时意外发现 nil”:( @SörenYannickSeitz 我猜你在 tableView:cellForRowAt: 函数中得到了这个,尝试调试它或添加一些打印语句。 也许.group.from.to 在其中一个元素中是nil,但是String! 你告诉Swift 他们永远不会是nil。尝试将它们更改为String? 仍然得到相同的错误:“线程 3:致命错误:在展开可选值时意外发现 nil”。我通过 print 语句检查了它们,没有一个值是 nil。 某事绝对是零。单步执行代码,直到遇到导致异常的行。然后再次运行,在该行停止并检查所有使用的值【参考方案2】:

试试这个代码。

你的模型。

typealias Fahrten = [FahrtenElement]

struct FahrtenElement: Codable 
    let group: String
    let from: String
    let to: String

    enum CodingKeys: String, CodingKey 
        case group = "group"
        case from = "from"
        case to = "to"
    

使用它,我正在使用它与具有相同结构的本地 json。

func getFehData()
    let url = Bundle.main.url(forResource: "fah", withExtension: "json")!
    do 
        let jsonData = try Data(contentsOf: url)
        let fahrten = try? JSONDecoder().decode(Fahrten.self, from: jsonData)

        print(fahrten)
    
    catch 
        print(error)
    

输出:(虚拟数据)

【讨论】:

它给了我一个错误:“从 '() throws -> ()' 类型的抛出函数到非抛出函数类型 '@convention(block) () -> Void' 的无效转换” @SörenYannickSeitz 检查编辑答案。 请描述您所做的事情以及它如何解决问题。这是为了帮助正在寻找类似于 OP 的解决方案的未来读者。 @dahiya_boy 重新加载数据时确实出现错误。 “线程 8:致命错误:在展开可选值时意外发现 nil” @SörenYannickSeitz 在哪一行出现错误?根据我的答案或其他答案,您实际上在做什么?

以上是关于Swift 4.2 中带有 JSON 数据的 Tableview的主要内容,如果未能解决你的问题,请参考以下文章

Swift 4.2 - 如何从 tableView 中的“didSelectRowAtIndexPath”方法调用“indexPath.row”到另一个类?

Swift 中带有“外部”数据源和委托的 UIPickerView

Swift 中带有自定义 TableViewCell 的核心数据图像

多细胞类型swift 4.2

UITableView Swift中带有布尔值的切换按钮

Swift - 解码数组 JSON 数据的数组