我的整个表格视图都以编程方式编写,并且数据来自JSON。我正在尝试按customer
对单元格进行分组,代码似乎是正确的,但是根本没有显示任何部分。
这是代码:
Portfolios.swift
import UIKit
struct Portfolios: Codable {
let customer, serial, rma, model: String
let manufacturer: String
}
PortfolioController.swift
import UIKit
class PortfolioController: UITableViewController {
var portfolios = [Portfolios]()
var portfoliosDic = [String:[Portfolios]]()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
view.backgroundColor = UIColor.blue
navigationItem.title = "Customer"
fetchJSON()
}
func fetchJSON(){
let urlString = "https://www.example.com/example/example.php"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, _, error) in
DispatchQueue.main.async {
if let error = error {
print("Failed to fetch data from url", error)
return
}
guard let data = data else { return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let res = try JSONDecoder().decode([Portfolios].self, from: data)
self.portfoliosDic = Dictionary(grouping: res, by: { $0.customer})
DispatchQueue.main.async {
self.tableView.reloadData()
}
self.portfolios = try decoder.decode([Portfolios].self, from: data)
self.tableView.reloadData()
} catch let jsonError {
print("Failed to decode json", jsonError)
}
}
}.resume()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return portfoliosDic.keys.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let keys = Array(portfoliosDic.keys)
let item = portfoliosDic[keys[section]]!
return item.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellId")
let keys = Array(portfoliosDic.keys)
let arr = portfoliosDic[keys[indexPath.section]]!
let customer = arr[indexPath.row]
let titleStr = [customer.serial, customer.manufacturer, customer.model].compactMap { $0 }.joined(separator: " - ")
//cell.textLabel?.text = titleStr
print(titleStr)
// Get references to labels of cell
cell.textLabel!.text = customer.serial
return cell
}
}
更新:
因为这是一个UIViewController Xcode,它告诉我删除override func
我添加了@IBOutlet weak var tableView: UITableView!
(由于某种原因,最终结果是一个空表)
改为使用UITableViewController:
import UIKit
class CustomerViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var sections = [Section]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellId")
navigationController?.navigationBar.prefersLargeTitles = true
fetchJSON()
}
func fetchJSON(){
let urlString = "https://www.example.com/example/example.php"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, _, error) in
DispatchQueue.main.async {
if let error = error {
print("Failed to fetch data from url", error)
return
}
guard let data = data else { return }
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let res = try decoder.decode([Portfolios].self, from: data)
let grouped = Dictionary(grouping: res, by: { $0.customer })
let keys = grouped.keys.sorted()
self.sections = keys.map({Section(name: $0, items: grouped[$0]!)})
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print("Failed to decode json", error)
}
}
}.resume()
}
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section = sections[section]
return section.items.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].name
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
let section = sections[indexPath.section]
let item = section.items[indexPath.row]
let titleStr = "\(item.serial) - \(item.manufacturer) - \(item.model)"
cell.textLabel!.text = titleStr
return cell
}
}
答案 0 :(得分:0)
首先为什么要对JSON解码两次?
由于未实现方法titleForHeaderInSection
,因此未显示任何部分。
反正该代码不可靠,因为不能保证各节的顺序。我建议为这些部分创建另一个结构。
struct Section {
let name : String
let items : [Portfolios]
}
struct Portfolios: Decodable {
let customer, serial, rma, model: String
let manufacturer: String
}
删除portfolios
和portfoliosDic
并声明数据源数组
var sections = [Section]()
对JSON进行分组,对键进行排序并将字典映射到Section
实例
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let res = try decoder.decode([Portfolios].self, from: data)
let grouped = Dictionary(grouping: res, by: { $0.customer })
let keys = grouped.keys.sorted()
self.sections = keys.map({Section(name: $0, items: grouped[$0]!)})
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print("Failed to decode json", error)
}
表视图数据源和委托方法是
override func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section = sections[section]
return section.items.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].name
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
let section = sections[indexPath.section]
let item = section.items[indexPath.row]
let titleStr = "\(item.serial) - \(item.manufacturer) - \(item.model)"
cell.textLabel!.text = titleStr
return cell
}
注意:
始终使cellForRowAt