如何在表格视图的各部分中修复单元格的分离集合? [英] How to fix the separation collections of cells in my sections in my tableview?

查看:71
本文介绍了如何在表格视图的各部分中修复单元格的分离集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此有人告诉我,将单元格划分为多个部分的数据模型是不好的.

So I've been told that my data model for separating my cells into sections is bad.

我在Tableview的cartItems,groupedItems和brandVC中有3个单独的集合.有人告诉我:

I have 3 separate collections in my Tableview cartItems, groupedItems, and brandTitle in the CartVC. and I've been told this:

您需要从一个仅代表截面数据的集合开始(每个截面数据将保存相应的行数据),这样您就可以对模型进行修改而不会发疯"

"You need to start over with a single collection representing nothing but sections data (where each piece of section data will hold the corresponding row data), so you can mutate the model without going insane"

"......建议避免为表视图的数据源使用多个数组,并使用Dictionary来馈送表视图不是一个好主意.您应该创建一个Model类型."

"...recommended to avoid multiple Arrays for the datasource of a table view and using Dictionary to feed the table view is not a good idea. You should create a Model type."

我只是真的不知道该怎么做,因为我一直在使用这些集合将单元格划分为几个部分,因此我花了数周的时间来生成并弄清楚这些,以便我可以成功地将单元格填充到适当的部分中在CartVC中

I just don't know really how to do so, since the collections I've been using to separate the cells into sections took me weeks to generate and figure out, so that I could successfully populate the cells in their appropriate sections in the CartVC

import UIKit

class CartViewController: UIViewController {

    var selectedProduct: ItemList!       // allows data to be passed into the CartVC

    // allows data to be sepearted into sections
    var cartItems: [CartItem] = []
    var groupedItems: [String: [CartItem]] = [:]
    var brandTitle: [String] = []

    @IBOutlet weak var cartTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        groupedItems = Dictionary(grouping: cartItems, by: {$0.itemList.brandName})
        brandTitle = groupedItems.map{$0.key}.sorted()
    }
}

extension CartViewController: UITableViewDelegate, UITableViewDataSource{

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

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let brand = brandTitle[section]
        return groupedItems[brand]!.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cartCell = tableView.dequeueReusableCell(withIdentifier: "CartCell") as! CartCell

        let brand = brandTitle[indexPath.section]
        let itemsToDisplay = groupedItems[brand]![indexPath.row]
        cartCell.configure(withCartItems: itemsToDisplay.productList)

        return cartCell
    }

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

        let headerTitle = brandTitle[section]
        cartHeader.brandName.text = "Brand: \(headerTitle)"

        return cartHeader
    }

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

    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let cartFooter = tableView.dequeueReusableCell(withIdentifier: "CartFooter") as! CartFooter

        let brand = brandTitle[section]
        let subtotal = groupedItems[brand]?.map { $0.getCartTotal() }.reduce(0, +) ?? 0
        cartFooter.cartTotal.text = String(subtotal)

        return cartFooter
    }

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 150
    }


import Foundation

class CartItem {
    var itemList: ItemList!

    init(itemList: ItemList) {

        self.itemList = itemList
    }

    func getCartTotal() -> Float {
        var subtotal: Float = 0
        if itemList.selectedOption == 1 {
            subtotal = subtotal + (Float(itemList.price1) * Float(itemList.count))
        } else if itemList.selectedOption == 2 {
            subtotal = subtotal + (Float(itemList.price2) * Float(itemList.count))
        } else if itemList.selectedOption == 3 {
           subtotal = subtotal + (Float(itemList.price3) * Float(itemList.count))
        }  else {
            fatalError("The impossible happend")
        }
        return subtotal
    }
}

class ItemList {
    var id: String
    var name: String
    var brand: String
    var price1: Float
    var price2: Float
    var price3: Float
    var weight1: String
    var weight2: String
    var weight3: String
    var imageUrl: String
    var selectedOption: Int
    var count: Int

    init(id: String,
         name: String,
         brand: String,
         price1: Float,
         price2: Float,
         price3: Float,
         weight1: String,
         weight2: String,
         weight3: String,
         imageUrl: String,
         selectedOption: Int,
         count: Int) {

        self.id = id
        self.name = name
        self.brand = brand
        self.price1 = price1
        self.price2 = price2
        self.price3 = price3
        self.weight1 = weight1
        self.weight2 = weight2
        self.weight3 = weight3
        self.imageUrl = imageUrl
        self.selectedOption = selectedOption
        self.count = count
    }

    convenience init(dictionary: [String : Any]) {
        let id = dictionary["id"] as? String ?? ""
        let name = dictionary["name"] as? String ?? ""
        let brand = dictionary["brand"] as? String ?? ""
        let price1 =  dictionary["price1"] as? Float ?? 0.0
        let price2 =  dictionary["price2"] as? Float ?? 0.0
        let price3 =  dictionary["price3"] as? Float ?? 0.0
        let weight1 =  dictionary["weight1"] as? String ?? ""
        let weight2 =  dictionary["weight2"] as? String ?? ""
        let weight3 =  dictionary["weight3"] as? String ?? ""
        let imageUrl =  dictionary["imageUrl"] as? String ?? ""
        let selectedOption = dictionary["selectedOption"] as? Int ?? 00
        let count= dictionary["count"] as? Int ?? 00

        self.init(id: id,
                  name: name,
                  brand: brand,
                  price1: price1,
                  price2: price2,
                  price3: price3,
                  weight1: weight1,
                  weight2: weight2,
                  weight3: weight3,
                  imageUrl: imageUrl,
                  selectedOption: selectedOption,
                  count: count)
    }

}

推荐答案

假设您所有购物车商品中只有 1个部分.您的模型会有什么?

Imagine you have just one section of all your cart items. What would you have as your model?

  • 标题
  • 一系列购物车商品

对吗?

好的,如果上面的讲得通,那么您将需要所述模型类型的倍数.再说一次现在,将其分解为更具体的术语.类似于实际的模型类型.除非您确实需要引用语义,否则总是建议从模型的值类型开始.

Okay if the above makes sense, you then would need multiple of that said model type. Right again? Now break that into more specific terms. Like actual model type. It's always good and recommended to start with value type for the models unless you really need the reference semantics.

struct CartItem {
    // intentionally renamed the ItemList to CartItem and stripped out most of the properties
    let name: String
    let brand: String
}
struct Section {
    let title: String
    let cartItems: [CartItem]
}

我不会自己初始化Section的数组,更多的是实现细节.但是,如果您必须从外部类型(例如 JSON )进行初始化,则可能需要减少(in :: _ :) .基本上,您将需要 一般转换Collection 的想法.或者也可以可编码.

I'm not going to initialize the array of Sections by myself, it's more of an implementation detail. But if you have to initialize that from external types (such as JSON) you may need the help of map(:), compactMap(:) or reduce(into:_:). Basically you will need the idea of Transforming a Collection in general. Or maybe Codable too.

那么您如何将上述Section类型与UITableView一起使用?仔细观察:

So how do you use the above Section type with your UITableView? Look closely:

class CartViewController: UIViewController {
    . . .
    // left out for the reader to initialize on his own
    let sections = [Section]()
    . . .
    . . .
}
extension CartViewController: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[section].count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        . . .
        let cartItem = sections[indexPath.section].cartItems[indexPath.row]
        . . .
    }
}

现在CartViewController中的所有其他位置,您将访问sections数组,并且将始终指向正确的对象.

Now every other places in your CartViewController you will access the sections array and you will always be pointing to the right object.

深入研究模型操作.您可以在模型类型本身中为不同的表示形式使用不同的辅助函数.像:

Diving deep into the model manipulation. You can have different helper functions in your model type itself for different representations. Like:

struct Section {
    let title: String
    let cartItems: [CartItem]

    static func groupedSectionsByBrand(from cartItems: [CartItem]) -> [Section] {
        let grouped = Dictionary(grouping: cartItems) { $0.brand }
        let sections = grouped.map { Section(title: $0.key, cartItems: $0.value) }
        return sections
    }
}

然后,您将可以通过仅传递CartItem的数组来生成所需的Section数组,例如:

Then you will be able to generate your desired array of Section by passing only the array of CartItem like:

let cartItems = [CartItems]() // have these values from elsewhere
let sections = Section.groupedSectionsByBrand(from: cartItems)

这篇关于如何在表格视图的各部分中修复单元格的分离集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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