Сгруппированные разделы не отображаются в виде таблицы - PullRequest
0 голосов
/ 16 мая 2019

Весь мой вид таблицы пишется программно, а данные поступают из 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
    }

}

UPDATE:

Поскольку это 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 голосов
/ 16 мая 2019

Прежде всего, почему вы декодируете 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 instance

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
}

Примечание:

Всегда ячейки dequeue в cellForRowAt

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...