如何基于JSON数组中的字段对tableview单元格进行分组 [英] How to group tableview cells based on field in JSON array

查看:80
本文介绍了如何基于JSON数组中的字段对tableview单元格进行分组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我在使用JSON数据创建数组并形成表格视图.

Essentially I have am using JSON data to create an array and form a tableview.

我希望表格单元格通过JSON数组中的字段之一进行分组.

I would like the table cells to be grouped by one of the fields from the JSON array.

这是JSON数据的样子:

This is what the JSON data looks like:

[{"customer":"Customer1","number":"122039120},{"customer":"Customer2","number":"213121423"}]

每个number需要按每个customer分组.

这怎么办?

这是我使用表实现JSON数据的方式:

This is how I've implemented the JSON data using the table:

CustomerViewController.swift

import UIKit

class CustomerViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, FeedCustomerProtocol {

    var feedItems: NSArray = NSArray()
    var selectedStock : StockCustomer = StockCustomer()
    let tableView = UITableView()
    @IBOutlet weak var customerItemsTableView: UITableView!

    override func viewDidLoad() {

        super.viewDidLoad()



        //set delegates and initialize FeedModel
        self.tableView.allowsMultipleSelection = true
        self.tableView.allowsMultipleSelectionDuringEditing = true

        self.customerItemsTableView.delegate = self
        self.customerItemsTableView.dataSource = self

        let feedCustomer = FeedCustomer()

        feedCustomer.delegate = self
        feedCustomer.downloadItems()

            }


    }


    func itemsDownloaded(items: NSArray) {

        feedItems = items
        self.customerItemsTableView.reloadData()
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Return the number of feed items

        print("item feed loaded")
        return feedItems.count

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        // Retrieve cell

        let cell = tableView.dequeueReusableCell(withIdentifier: "customerGoods", for: indexPath) as? CheckableTableViewCell

        let cellIdentifier: String = "customerGoods"
        let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!

        // Get the stock to be shown
        let item: StockCustomer = feedItems[indexPath.row] as! StockCustomer
        // Configure our cell title made up of name and price


        let titleStr = [item.number].compactMap { $0 }.joined(separator: " - ")


        return myCell
    }

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        tableView.cellForRow(at: indexPath)?.accessoryType = .none
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {


        tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark

        let cellIdentifier: String = "customerGoods"
        let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
        myCell.textLabel?.textAlignment = .left


    }

}

FeedCustomer.swift:

import Foundation

protocol FeedCustomerProtocol: class {
    func itemsDownloaded(items: NSArray)
}


class FeedCustomer: NSObject, URLSessionDataDelegate {



    weak var delegate: FeedCustomerProtocol!

    let urlPath = "https://www.example.com/example/test.php"

    func downloadItems() {

        let url: URL = URL(string: urlPath)!
        let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)

        let task = defaultSession.dataTask(with: url) { (data, response, error) in

            if error != nil {
                print("Error")
            }else {
                print("stocks downloaded")
                self.parseJSON(data!)
            }

        }

        task.resume()
    }

    func parseJSON(_ data:Data) {

        var jsonResult = NSArray()

        do{
            jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray

        } catch let error as NSError {
            print(error)

        }

        var jsonElement = NSDictionary()
        let stocks = NSMutableArray()

        for i in 0 ..< jsonResult.count
        {

            jsonElement = jsonResult[i] as! NSDictionary

            let stock = StockCustomer()

            //the following insures none of the JsonElement values are nil through optional binding
            if let number = jsonElement["number"] as? String,
                let customer = jsonElement["customer"] as? String,

            {

                stock.customer = customer
                stock.number = number
            }

            stocks.add(stock)

        }

        DispatchQueue.main.async(execute: { () -> Void in

            self.delegate.itemsDownloaded(items: stocks)

        })
    }
}

StockCustomer.swift:

import UIKit

class StockCustomer: NSObject {

    //properties of a stock

    var customer: String?
    var number: String?


    //empty constructor

    override init()
    {

    }

    //construct with @name and @price parameters

    init(customer: String) {

        self.customer = customer



    }



    override var description: String {
        return "Number: \(String(describing: number)), customer: \(String(describing: customer))"

    }

}

推荐答案

您可以使用Dictionary initializer

init(grouping:by:)

上述方法init将根据您在closure中提供的密钥对给定的sequence进行分组.

The above method init will group the given sequence based on the key you'll provide in its closure.

此外,对于解析此类JSON,您可以轻松地使用Codable而不是手动完成所有工作.

Also, for parsing such kind of JSON, you can easily use Codable instead of manually doing all the work.

因此,首先使StockCustomer符合Codable协议.

So, for that first make StockCustomer conform to Codable protocol.

class StockCustomer: Codable {
    var customer: String?
    var number: String?
}

接下来,您可以像这样解析数组:

Next you can parse the array like:

func parseJSON(data: Data) {
    do {
        let items = try JSONDecoder().decode([StockCustomer].self, from: data)
        //Grouping the data based on customer
        let groupedDict = Dictionary(grouping: items) { $0.customer } //groupedDict is of type - [String? : [StockCustomer]]
        self.feedItems = Array(groupedDict.values)
    } catch {
        print(error.localizedDescription)
    }
}

在此处详细了解init(grouping:by:): https://developer. apple.com/documentation/swift/dictionary/3127163-init

[[StockCustomer]]类型的CustomerViewController中使feedItems对象

现在,您可以通过以下方式实现UITableViewDataSource方法:

Now, you can implement UITableViewDataSource methods as:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.feedItems.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "customerGoods", for: indexPath) as! CheckableTableViewCell
    let items = self.feedItems[indexPath.row]
    cell.textLabel?.text = items.compactMap({$0.number}).joined(separator: " - ")
    //Configure the cell as per your requirement
    return cell
}

尝试用所有零碎的方法来实施该方法,如果遇到任何问题,请告知我.

Try implementing the approach with all the bits and pieces and let me know in case you face any issues.

这篇关于如何基于JSON数组中的字段对tableview单元格进行分组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆