如何将 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 中的数组(模型类)中?