如何将 JSON 获取到 Swift 到 tableView 作为部分和行?

Posted

技术标签:

【中文标题】如何将 JSON 获取到 Swift 到 tableView 作为部分和行?【英文标题】:How to Fetch JSON to Swift to tableView as Sections and Rows? 【发布时间】: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)

        

【问题讨论】:

获取文件来自本站jsonplaceholder.typicode.com/posts 【参考方案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 相关的所有内容。

【讨论】:

以上是关于如何将 JSON 获取到 Swift 到 tableView 作为部分和行?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JSON 数据存储到 swift3 中的数组(模型类)中?

在swift 5中将json数据获取到tableview

如何从函数内部获取 JSON 数据并将其快速显示在文本字段上?

如何通过 JSON 将数组从 php 解压到 Swift

swift 如何检查来自 Json 的 NULL 值

将数据发布到 PHP 并使用 SwiftyJSON 获取 JSON