【问题标题】:How to Fetch JSON to Swift to tableView as Sections and Rows?如何将 JSON 获取到 Swift 到 tableView 作为部分和行?
【发布时间】:2019-09-07 05:21:37
【问题描述】:

我想问如何实现文件,因为部分取决于 userId 然后在 tableview 中再次显示

我开始构建简单的项目,我获取 json 文件作为解码器并在表格视图中显示所有内容

func fetchUsers(using url: String){
    let url = URL(string: url)!
    let _ = URLSession.shared.dataTask(with: url){ (data,response,error)
        in
        guard let data = data else {return}
        do{
            let objects = try JSONDecoder().decode([User].self, from: data)  // decode * ( Codable )
            self.users = objects
        } catch{
            print("error loading data cause: \(error)")
            }
        }.resume()
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "users",for: indexPath) as? customeCellTableViewCell{
        let indexRow = users[indexPath.row]
        cell.dataModel(forModel: indexRow)
     return cell
    }
    return UITableViewCell()
}



private func numberOfUsers(in users: [User]) -> Int {

            return 1
        }

        func numberOfSections(in tableView: UITableView) -> Int {

            return numberOfUsers(in: self.users)

        }

【问题讨论】:

标签: ios json swift api tableview


【解决方案1】:

就像@vadian 提到的,应该避免使用元组,所以这里有一个改进的解决方案。

我们可以使用结构来代替元组来保存分组数据

struct UsersByID {
    let id: Int
    var users : [User]
}

然后将load函数改为

func load(withUsers users: [User]) {
    let dict = Dictionary(grouping: users) { return $0.userID }
    usersByID = dict.map { (key, values) in
        return UsersByID(id: key, users: values)
    }.sorted(by: { $0.id < $1.id })
}

其余代码相同,但将key 替换为id,将value 替换为users


旧解决方案

首先创建一个字典来保存你的部分(键)和行(值)作为视图控制器中的属性

var usersByID = [(key: Int, value: [User])]()

然后使用来自 json 的数组使用 grouping:by: 填充该字典

func load(withUsers users: [User]) {
    usersByID = Dictionary(grouping: users, by: { user in
        user.userID }).sorted(by: { $0.0 < $1.0})
}

那么表格视图函数使用这个字典


override func numberOfSections(in tableView: UITableView) -> Int {
    return usersByID.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return usersByID[section].value.count
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return String(usersByID[section].key)
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath)

    let user = usersByID[indexPath.section].value[indexPath.row]
    cell.textLabel?.text = user.title
    //...

    return cell
}

【讨论】:

  • 请不要建议将元组作为数据源。 Apple 明确不鼓励开发人员这样做。
【解决方案2】:
    func numberOfSections(in collectionView: UICollectionView) -> Int {
            return datesArr.count
        }

        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

            if (contractsDict.keys.contains(datesArr[section])) {
                return contractsDict[datesArr[section]]!.count
            }

            return 0
        }

        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ContractsCollectionViewCell

            DispatchQueue.main.async {
                if (self.contractsDict.keys.contains(self.datesArr[indexPath.section])) {
                    for _ in 0..<(self.contractsDict[self.datesArr[indexPath.section]]!.count) {
                        cell.contract = self.contractsDict[self.datesArr[indexPath.section]]![indexPath.row]
                        cell.delegate = self
                    }
                }
            }

            return cell
        }
    }
}

    ContractServices.shared.fetchAllContracts(completion: { (contracts, err) in
                    DispatchQueue.main.async {
                        if (err != nil) {
                            print(err!, "1323")
                            return
                        }

                        for contract in (contracts?.data)! {
                            self.allContractsArr.append(contract)
                            if let callDate = contract.revdat {
                                let formatterGet = DateFormatter()
                                formatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"
                                let newFormat = DateFormatter()
                                newFormat.dateFormat = "dd MMM yyyy"

                                if let date = formatterGet.date(from: callDate) {
                                    self.datesArr.append(newFormat.string(from: date))
                                }
                            }
                        }

                        for i in 0..<self.allContractsArr.count {
                            if let callDate = self.allContractsArr[i].revdat {
                                let formatterGet = DateFormatter()
                                formatterGet.dateFormat = "yyyy-MM-dd HH:mm:ss"
                                let newFormat = DateFormatter()
                                newFormat.dateFormat = "dd MMM yyyy"

                                if let date = formatterGet.date(from: callDate) {
                                    self.allContractsArr[i].revdat = newFormat.string(from: date)
                                }
                            }
                        }

                        self.allContractsArr = self.allContractsArr.sorted(by: { ($0.revdat)! > ($1.revdat)! })
                        self.contractsDict = Dictionary(grouping: self.allContractsArr, by: { ($0.revdat)! })
                        let newFormat = DateFormatter()
                        newFormat.dateFormat = "dd MMM yyyy"
                        self.datesArr = Array(Set(self.datesArr))
                        self.datesArr = self.datesArr.sorted(by: { newFormat.date(from: $0)! > newFormat.date(from: $1)! })

                        self.contractListCV.reloadData()

                        DispatchQueue.main.async {
                            self.activityBackView.isHidden = true
                            self.activity.isHidden = true
                            self.activity.stopAnimating()
                            self.design()
                        }

                    }
                })

这就是我正在做的。 获取数组格式的数据,通过 grouping(by:) 方法将它们转换为 Dictionary,然后在这些字典数据上操作与 collectionview 相关的所有内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-16
    • 2020-04-24
    • 1970-01-01
    • 2017-07-26
    • 2018-12-23
    • 1970-01-01
    • 2020-11-11
    • 2017-10-11
    相关资源
    最近更新 更多