【问题标题】:Swift segmented contorl show/hide cells in uicollectionview depending on firebase logic根据firebase逻辑,在uicollectionview中快速分段控制显示/隐藏单元格
【发布时间】:2020-05-25 20:52:55
【问题描述】:

我很难根据 FB 实时数据库中的项目子节点来显示/隐藏我的 collectionview 单元格。该问题由三部分组成:FB 数据库、一个collectionview 和一个分段控件。我的目标是在 collectionview 中显示不同的单元格,具体取决于项目是否具有具有特定字符串值的子项。

我的数据库如下所示:

Items
   category1
      item1
         name: item1
         imageUrl: item1Url
         logic
            one
            three
      item2
         name: item1
         imageUrl: item1Url
         logic
            two
            three
   category2
      item1
         name: item1
         imageUrl: item1Url
         logic
            two
            four
      item2
         name: item1
         imageUrl: item1Url
         logic
            one
            two

我还有一个自定义 Product 类来在他们的单元格中显示我的项目:

class Product {
    var category: String?
    var name: String?
    var imageUrl: String?

    init(rawData: [String: AnyObject]) {
        name = rawData["name"] as? String
        imageUrl = rawData["imageUrl"] as? String
        category = rawData["category"] as? String
    }
} 

我使用这个功能从 firebase 数据库加载我的项目:

func loadCategoryName() {
    ref = Database.database().reference().child("Items").child(selectedCategoryFromPreviousVC)
    ref.observeSingleEvent(of: .value) { (snapshot) in
        if let data = snapshot.value as? [String: AnyObject] {
            self.itemArray = []
            let rawValues = Array(data.values)
            for item in rawValues {
                let product = Product(rawData: item as! [String: AnyObject])
                product.category = self.selectedCategoryFromPreviousVC
                self.itemArray.append(product)
            }

            // Sort item array by rating; if rating is same, sort by name
            self.itemArray.sort { (s1, s2) -> Bool in
                if s1.rating == s2.rating {
                    return s1.name! < s2.name!
                } else {
                    return s1.rating > s2.rating
                }
            }
            self.collectionView?.reloadData()
        }
    }
}

我的 itemArray 现在包含我的所有商品作为自定义产品,我可以在它们的单元格中显示它们。

我的分段控件:

func someFunc() {
    let segmentController = UISegmentedControl(items: ["one", "two", "three", "four"])

    segmentController.selectedSegmentIndex = 0
    self.navigationItem.titleView = segmentController
    segmentController.addTarget(self, action: #selector(handleSegment), for: .valueChanged)
}

@objc fileprivate func handleSegment() {
    print(segmentController.selectedSegmentIndex)
}

使用 handleSegment 函数,我可以打印出已选择的段。但这就是问题发生的地方。我尝试创建新数组来拆分项目,以便项目根据它们的“逻辑”子节点位于一个数组中。但是我无法制作 Product 类型的数组,以便我可以使用它们来重新填充 collectionview。此外,我不确定在我的数据库中存储逻辑部分的最佳方式是什么。

【问题讨论】:

    标签: ios swift firebase-realtime-database uicollectionview uisegmentedcontrol


    【解决方案1】:

    扩展您的产品类别:

    class Product {
       ...
       let logic: [String]?
    
       init(...) {
          ...
          logic = rawData["logic"] as? [String]
       }
    }
    

    在你的 CollectionViewDataSource 添加一些变量来存储当前状态

    var products: [Products]
    var filteredProducts: [Product]
    var currentFilter: String? {
       didSet {
          guard let currentFilter = currentFilter else {
             filteredProducts = products
             return
          }
          filteredProducts = products.filter { product in
             return product.logic.contains(currentFilter)
          }
       }
    }
    

    扩展你的 handleSegment 函数:

    @objc fileprivate func handleSegment() {
       print(segmentController.selectedSegmentIndex)
       currentFilter = segmentController.titleForSegment(at: segmentController.selectedSegmentIndex)
       collectionView.reloadData()
    }
    

    在您的 collectionView 数据源中,使用 filtersProducts 构建单元格。

    【讨论】:

    • 非常感谢 Robin 的帮助,filteredProducts 数组和 currentFilter 变量是我花了一段时间才知道该怎么做的!在 handleSegment 函数中,我必须将 currentFilter 更改为 segmentController.titleForSegment(at: segmentController.selectedSegmentIndex) 但现在它可以正常工作了。
    • 我仍然有一个问题:我真的不明白我应该如何将我的“逻辑”节点存储在数据库中的项目下。现在我简单地将“逻辑”作为键,并将一、二、三或四作为每个项目的值。这行得通,但是这样每个项目只能得到一个它显示的值,我想要多个。我看到的唯一解决方案是将数字保存为逻辑节点的子节点,然后分配一个随机键,如 item1 -> logic -> one:是,三:是,但这似乎有点麻烦?
    • 太好了,你想通了! :) 要存储您的逻辑节点,只需为键“逻辑”添加一个字符串类型的数组(就像我在产品模型中所做的那样)。这样,您的模型应该在本地数据库中表示,就像在 firebase 中一样
    • 我知道您可以在使用 firestore 时通过选择“array”轻松地做到这一点,但是在使用 db 时我找不到任何方法来做到这一点,因为我无法在孩子下保存值没有它们都有一个键和一个值(这使它成为字典而不是数组)
    • 在实时数据库中,您只需添加一个值为["one", "two", "three"] 的字段logic,它将被映射为数组。在 FB DB 中显示为 0:“一”,1:“二”...但在 JSON 中,它是一个没有索引的普通数组
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多