你如何在 tableview 中对部分进行分组?

How do you do you group sections in tableview?

我想做的是将 TableView 中的部分分组。通过按 storeName 对它们进行排序,以便我可以将项目分开以转到其适当的部分并按 StoreName.

排列

我试图在每个商店的列表中显示几个不同的项目部分。通过根据 StoreName 对部分进行分组。

Items 数组包含每个部分中每个项目的所有项目,并显示该项目属于哪个商店。

我如何能够对特定商店的部分进行分组?

我知道我很擅长对我的部分进行分组,但我只是不确定如何使其正常工作以及如何连接到我的 Custom HeaderCell。我在我的 StoreVC 中编写了一个名为 attemptToAssembleStoreGroups()

的函数

我只是想知道我如何才能根据 storeName 将我的商品分组在一起,以便每个商店都有自己的部分,并有自己的商品列表。

struct ItemSelection {
    let store: String
    let productName: String
    let productImage: UIImage
    let quantity: String
    let total: String
}

struct ItemSection {
    let title : String
    let stores : [ItemSelection]
}

class StoreVC: UITableViewController {

      fileprivate let cellId = "id123"

        let items = [
          ItemSelection(store: "Walmart",
               productName: "Bionicle",
               productImage: #imageLiteral(resourceName: "Bionicle"),
               quantity: "4",
               total: "24"),
          ItemSelection(store: "Walmart",
               productName: "PokeBall",
               productImage: #imageLiteral(resourceName: "PokeBall"),
               quantity: "2",
               total: "30"),
          ItemSelection(store: "Target",
               productName: "Beer",
               productImage: #imageLiteral(resourceName: "Beer"),
               quantity: "2",
               total: "30"),
          ItemSelection(store: "Lego Store",
               productName: "Star Wars Set",
               productImage: #imageLiteral(resourceName: "Star_Wars_Set"),
               quantity: "4",
               total: "256"),
          ItemSelection(store: "Lego Store",
               productName: "Indiana Jones Set",
               productImage: #imageLiteral(resourceName: "Indiana_Jones_Set"),
               quantity: "2",
               total: "88"),
          ItemSelection(store: "Amazon",
               productName: "Coconut Milk",
               productImage: #imageLiteral(resourceName: "Coconut_Milk"),
               quantity: "4",
               total: "20"),
          ItemSelection(store: "Amazon",
               productName: "32 inch Tv",
               productImage: #imageLiteral(resourceName: "TV"),
               quantity: "1",
               total: "156"),
          ItemSelection(store: "Amazon",
               productName: "Amazon Echo",
               productImage: #imageLiteral(resourceName: "Amazon_Echo"),
               quantity: "1",
               total: "80"),
          ItemSelection(store: "Amazon",
               productName: "Grill",
               productImage: #imageLiteral(resourceName: "Grill"),
               quantity: "3",
               total: "90"),
          ItemSelection(store: "Amazon",
               productName: "Coconut Bar",
               productImage: #imageLiteral(resourceName: "coconuts"),
               quantity: "4",
               total: "240")
         ]

      var itemSelection = [[ItemSelection]]()
      var storeArray = [String]()
      var itemSections = [ItemSection]()

     override func viewDidLoad() {
        super.viewDidLoad()

        for index in self.items {
            storeArray.append(index.store)
        }

        let groupedDictionary = Dictionary(grouping: items, by: {String([=10=].store.prefix(1))})
        let keys = groupedDictionary.keys.sorted()
        itemSections = keys.map{ItemSection(title: [=10=], stores: groupedDictionary[[=10=]]!.sorted(by: {[=10=].store < .store}))}
     }



     override func numberOfSections(in tableView: UITableView) -> Int {
         return itemSections.count
     }

     override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         return itemSections[section].stores.count
     }

     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! StoreCell
         let itemSelections = itemSelection[indexPath.section][indexPath.row]
         cell.itemSelction = itemSelections
         return cell
     }

     override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
         let cartHeader = tableView.dequeueReusableCell(withIdentifier: "Header") as! HeaderCell

         let stores = itemSelection[section]

         cartHeader.storeName.text = "Store: \(stores)"

         return cartHeader
     }

     override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
         return 45
     }

}

class StoreCell: UITableViewCell {

    @IBOutlet weak var itemQty: UILabel!
    @IBOutlet weak var itemName: UILabel!
    @IBOutlet weak var itemPrice: UILabel!
    @IBOutlet weak var itemImage: UIImage!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    var itemSelection: ItemSelection! {
        didSet {
            itemName.text = itemSelection.productName
            itemQty.text = "Qty: \(itemSelection.quantity)"
            itemPrice.text = "$\(itemSelection.total)"
            itemImage.image = itemSelection.productImage
        }

    }

}

class HeaderCell: UITableViewCell {

    @IBOutlet weak var storeName: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

找到我的解决方案

import Foundation

struct Items {
    let store: String
    let productName: String
    let productImage: UIImage
    let quantity: String
    let price: String
}

extension Items: Comparable {
    static func < (lhs: Items, rhs: Items) -> Bool {
        if lhs.store < rhs.store { return true }
        else { return lhs.store == rhs.store && lhs.productName < rhs.productName }
    }
}

extension Items {
    static let retail: [Items] = [
        .init(store: "Amazon",
              productName: "Care Bear",
              productImage: #imageLiteral(resourceName: "Bear"),
              quantity: "4",
              price: "156"),
        .init(....
    ]
}

import Foundation

class ItemDataSource: NSObject {
    var sections: [String: [Items]] = [:]

    var items: [String] {
        return sections.keys.sorted()
    }

    var indexes: [String] {
        return items
            .map { String([=11=].first!) }
            .reduce(into: Set<String>(), { [=11=].insert() })
            .sorted()
    }

    init(stores: [Items]) {
        for store in retail.sorted(by: <) {
            let items = store.items
            if var stores = sections[items] {
                stores.append(store)
                sections[items] = stores
            } else {
                sections[items] = [store]
            }
        }
    }
}

class StoreHeader: UITableViewCell {

    @IBOutlet weak var dispensaryName: UILabel!

    var store: String? {
        didSet { storeName.text = "Store: \(store!)" }
    }

}

class StoreCell: UITableViewCell {

    @IBOutlet weak var productImage: UIImageView!
    @IBOutlet weak var productQty: UILabel!
    @IBOutlet weak var productPrice: UILabel!
    @IBOutlet weak var productName: UILabel!

    var product: String? {
        didSet { productName.text = product }
    }
    var quantity: String? {
        didSet { productQty.text = "Qty: \(quantity!)" }
    }
    var price: String? {
        didSet { productPrice.text = "$\(price!)" }
    }
    var img: UIImage? {
        didSet { productImage.image = img }
    }

}

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    let dataSource: ItemDataSource = .init(stores: Items.stores)

    @IBOutlet weak var tableView: UITableView!

    func numberOfSections(in tableView: UITableView) -> Int {
        return dataSource.sections.count
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let store = dataSource.items[section]
        return dataSource.sections[store]?.count ?? 0
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         let storeCell = tableView.dequeueReusableCell(withIdentifier: "StoreCell") as! StoreCell
        let store = dataSource.items[indexPath.section]
        let storeItem = dataSource.sections[store]?[indexPath.row]

        storeCell.product = storeItem?.productName
        storeCell.price = storeItem?.price
        storeCell.quantity = storeItem?.quantity
        storeCell.img = storeItem?.productImage

        return storeCell
    }
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let storeHeader = tableView.dequeueReusableCell(withIdentifier: "StoreHeader") as! StoreHeader
        storeHeader.store = dataSource.items[section]
        return storeHeader
    }
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 45
    }

或者,您可以将 ItemSelection 内容分解成一个单独的 class。

Dictionary(grouping:by:) 使您能够将数组转换为按您指定的任何键分组的字典。下面的代码按商店名称对其进行分组。

我使用了 lazy 变量,因此在初始化 class 时它们并没有全部初始化。一切都在需要时进行初始化。

storeNames 从字典键中检索。

通过从我从初始数组创建的字典中查找值来检索每个商店的元素。

class StoreInfoDataManager {

    struct ItemSelection {
        let storeName: String
        let productName: String
        let productImage: UIImage
        let quantity: String
        let total: String
    }

    lazy var storeDictionary: [String: [ItemSelection]] = {
        return Dictionary(grouping: itemSelections) { [=10=].storeName }
    }()

    // These are the keys for your sections
    lazy var storeNames: [String] = {
        return Array(storeDictionary.keys).sorted()
    }()

    // This returns an array of items in the store
    func items(for store: String) -> [ItemSelection]? {
        return storeDictionary[store]
    }

    lazy var itemSelections: [ItemSelection] = {
        return [
            ItemSelection(storeName: "Walmart",
                          productName: "Bionicle",
                          productImage: #imageLiteral(resourceName: "Bionicle"),
                          quantity: "4",
                          total: "24"),
            ItemSelection(storeName: "Walmart",
                          productName: "PokeBall",
                          productImage: #imageLiteral(resourceName: "PokeBall"),
                          quantity: "2",
                          total: "30"),
            ItemSelection(storeName: "Target",
                          productName: "Beer",
                          productImage: #imageLiteral(resourceName: "Beer"),
                          quantity: "2",
                          total: "30"),
            ItemSelection(storeName: "Lego Store",
                          productName: "Star Wars Set",
                          productImage: #imageLiteral(resourceName: "Star_Wars_Set"),
                          quantity: "4",
                          total: "256"),
            ItemSelection(storeName: "Lego Store",
                          productName: "Indiana Jones Set",
                          productImage: #imageLiteral(resourceName: "Indiana_Jones_Set"),
                          quantity: "2",
                          total: "88"),
            ItemSelection(storeName: "Amazon",
                          productName: "Coconut Milk",
                          productImage: #imageLiteral(resourceName: "Coconut_Milk"),
                          quantity: "4",
                          total: "20"),
            ItemSelection(storeName: "Amazon",
                          productName: "32 inch Tv",
                          productImage: #imageLiteral(resourceName: "TV"),
                          quantity: "1",
                          total: "156"),
            ItemSelection(storeName: "Amazon",
                          productName: "Amazon Echo",
                          productImage: #imageLiteral(resourceName: "Amazon_Echo"),
                          quantity: "1",
                          total: "80"),
            ItemSelection(storeName: "Amazon",
                          productName: "Grill",
                          productImage: #imageLiteral(resourceName: "Grill"),
                          quantity: "3",
                          total: "90"),
            ItemSelection(storeName: "Amazon",
                          productName: "Coconut Bar",
                          productImage: #imageLiteral(resourceName: "coconuts"),
                          quantity: "4",
                          total: "240")
        ]
    }()
}