在 tableview 中填充数组字典的高效和干净的方法

Posted

技术标签:

【中文标题】在 tableview 中填充数组字典的高效和干净的方法【英文标题】:Efficient and Clean way of populating array dictionary in tableview 【发布时间】:2018-11-19 10:58:23 【问题描述】:

有人能说出用字典数组填充 tableView 的简洁高效的方法吗?我有模型Sale,其中包含 saleAmount、soldBy、division、saleDate。每个部门可能包含许多销售数据,并希望按每个部门分隔销售数据。此外,在 tableView 标题中,我想显示部门名称以及特定部门的总销售额

class Sale  

    var saleAmount : Double = 0.00 
    var soldBy : String = ""
    var division : String = ""
    var saleDate : Date?

我收到数据并存储在

var sales : [Sale] = [Sale]()

然后我将数据处理到每个“部门”的字典中

var salesDict : [String : Sale] = [String : Sale] ()
func createIndex<Key, Element>(elms:[Element], extractKey:(Element) -> Key) -> [Key:Element] where Key : Hashable 
        return elms.reduce([Key:Element]())  (dict, elm) -> [Key:Element] in
            var dict = dict
            dict[extractKey(elm)] = elm
            return dict
        
    

salesDict = createIndex(elms: sales, extractKey: $0.division)
salesSection = salesDict.compactMap()$0.key // To store keys

print(saleDict) // ["division1": Clientname.Sale, "division2": Clientname.Sale, "division3": Clientname.Sale, "division4": Clientname.Sale]

并填充 tableView

func numberOfSections(in tableView: UITableView) -> Int 

       return salesSection.count
    

数据未正确填充

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int  

        return [salesDict[salesSection[section]]?.soldBy].count

    



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

            let saleItem = salesDict[salesSection[indexPath.section]]
            let cell = tableView.dequeueReusableCell(withIdentifier: "FoldingCell", for: indexPath) as! SaleHistoryTableViewCell

cell.saleAmountLabel.text = ("\(String(describing: saleItem?.saleAmount))")
    

 func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 

        return salesSection[section]
    

【问题讨论】:

你能详细说明Data is not populating correctly吗? 我能够将对象数组转换为每个部门的字典。但是对于每个部门,只有一条记录填充在 tableview 中。看到 Fabio 的解决方案后,我觉得我在创建 var salesDict 时犯了一个错误:[String : Sale] = [String : Sale] ()。它应该是 var salesDict : [String : [Sale]] = [String : [Sale]] () 代替。 【参考方案1】:

试试这个游乐场:

import UIKit
import PlaygroundSupport

class Sale 
    var saleAmount : Double = 0.00
    var soldBy : String = ""
    var division : String = ""
    var saleDate : Date?

    init(saleAmount : Double = 0.0, soldBy : String = "" , division : String = "", saleDate : Date? = nil) 
        self.saleAmount = saleAmount
        self.soldBy = soldBy
        self.division = division
        self.saleDate = saleDate
    


class VC: UITableViewController 

    var salesGroupedByDivision: [String: [Sale]]!

    init() 
        super.init(style: .grouped)
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        let sales = [
            Sale(saleAmount: 1.0, division: "1"),
            Sale(saleAmount: 2.0, division: "1"),
            Sale(saleAmount: 3.0, division: "2")
        ]
        salesGroupedByDivision = Dictionary(grouping: sales, by:  $0.division )

    

    required init?(coder aDecoder: NSCoder) 
        fatalError()
    

    override func numberOfSections(in tableView: UITableView) -> Int 
        return salesGroupedByDivision.keys.count
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        let division = Array(salesGroupedByDivision.keys)[section]
        return salesGroupedByDivision[division]?.count ?? 0
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        let division = Array(salesGroupedByDivision.keys)[indexPath.section]
        let sale = salesGroupedByDivision[division]?[indexPath.row]
        cell.textLabel?.text = "\(sale?.saleAmount)"
        return cell
    

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
        let division = Array(salesGroupedByDivision.keys)[section]
        return "\(division) \(salesGroupedByDivision[division]?.reduce(0,  $0 + $1.saleAmount ) ?? 0)"
    


let vc = VC()

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = vc

【讨论】:

效果很好。部门名称和每条记录都正确显示。如何将每个部门的总销售额与部门名称一起放在标题中? 我需要总销售额而不是每个部门的总记录。 好吧,我之前没明白你的意思。立即查看 太棒了。谢谢法比奥。【参考方案2】:

用 struct 试试:

struct Sale 
var saleAmount : Double = 0.00 
var soldBy : String = ""
var division : String = ""
var saleDate : Date?

类 ViewController : UIViewController

var arrayOfSaleData = [Sale]()

override func viewDidLoad()

    loadDataIntoArray()


func loadDataIntoArray()


     let mainSaleAmount = saleAmountData as? Double ?? 0
     let sold = soldData as? String ?? ""
     let div = divisionData as? String ?? ""
     let mainSaleDate = saleDateData as! Date

      //populate your struct with the received data                 
      let allData = Sale(saleAmount: mainSaleAmount , soldBy: sold , division: div , saleDate: mainSaleDate )

      self.arrayOfSaleData(allData)

      DispatchQueue.main.async 
      tabelView.reloadData()

      

 

extension ViewController : UITableViewDataSource, UITableViewDelegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
         -> Int 

        return arrayOfSaleData.count




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


        let cell = Bundle.main.loadNibNamed("YourTableViewCell", owner: self, options: nil)?.first as! YourTableViewCell
        //Here you can assign your table view cell elements with data from your struct array
        cell.saleAmountLabel.text = arrayOfSaleData[indexPath.row].saleAmount

        return cell


【讨论】:

以上是关于在 tableview 中填充数组字典的高效和干净的方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSMutableDictionary 和数组填充单元格的 TableView

使用字典值在 tableView 内填充 collectionView 的标签

从字典数组 Swift 中填充 UITableView

使用核心数据和数组从 TableView 中插入和删除行

填充 TableView 中的 JSON 数组和 CoreData

从单个数组数据和多个部分填充 tableView