【问题标题】:How to fix the separation collections of cells in my sections in my tableview?如何在我的表格视图中修复我的部分中的单元格的分离集合?
【发布时间】:2020-01-02 06:00:36
【问题描述】:

所以有人告诉我,我用于将单元格分成多个部分的数据模型很糟糕。

我的 Tableview cartItems、groupedItems 和 CartVC 中的 brandTitle 中有 3 个单独的集合。有人告诉我:

“您需要从一个只代表部分数据的集合重新开始(其中每个部分数据将保存相应的行数据),因此您可以在不发疯的情况下改变模型”

"...建议避免表视图的数据源使用多个数组,并且使用 Dictionary 来提供表视图不是一个好主意。您应该创建一个模型类型。"

我真的不知道该怎么做,因为我用来将单元格分成多个部分的集合花了我几周的时间来生成和弄清楚,这样我就可以成功地将单元格填充到相应的部分中在 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)
    }

}

【问题讨论】:

  • 你能说明ItemList的定义吗?
  • 刚刚贴出来

标签: swift uitableview collections model


【解决方案1】:

想象一下,您的购物车中只有 一个部分。你的模型是什么?

  • 一个标题
  • 购物车物品数组

对吗?


好的,如果上述内容有意义,那么您将需要多个上述模型类型。又对了?现在将其分解为更具体的术语。像实际的模型类型。除非您确实需要引用语义,否则建议从模型的值类型开始总是好的。

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]
}

我不会自己初始化Sections的数组,更多的是实现细节。但如果您必须从外部类型(例如 JSON)初始化它,您可能需要 map(:)compactMap(:)reduce(into:_:) 的帮助。基本上你需要一般地转换Collection的想法。或者也可能是Codable


那么如何将上面的Section 类型与UITableView 一起使用?仔细看:

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 数组,并且您将始终指向正确的对象。


深入了解模型操作。您可以在模型类型本身中为不同的表示提供不同的辅助函数。喜欢:

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 数组,例如:

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

【讨论】:

  • 我一直在运行测试,很快就会告诉你结果
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 2017-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
相关资源
最近更新 更多