分组的节未显示在表格视图中

时间:2019-05-16 13:12:43

标签: ios json swift uitableview

我的整个表格视图都以编程方式编写,并且数据来自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
    }

}

1 个答案:

答案 0 :(得分:0)

首先为什么要对JSON解码两次?

由于未实现方法titleForHeaderInSection,因此未显示任何部分。

反正该代码不可靠,因为不能保证各节的顺序。我建议为这些部分创建另一个结构。

struct Section {
    let name : String
    let items : [Portfolios]
}

struct Portfolios: Decodable {
    let customer, serial, rma, model: String
    let manufacturer: String
}

删除portfoliosportfoliosDic并声明数据源数组

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

中的单元出队