获取 TableviewCells 以显示从 firebase 提取的不同数据并在 CollectionView 中显示它们

Posted

技术标签:

【中文标题】获取 TableviewCells 以显示从 firebase 提取的不同数据并在 CollectionView 中显示它们【英文标题】:Get TableviewCells to display different data that is extracted from firebase and show them in CollectionView 【发布时间】:2020-03-17 04:20:41 【问题描述】:

我有这两个结构,我从 Firebase Database 获取的数据,我不知道如何让每个 tableview 单元格显示不同的集合视图,我在 xib 文件中有两个单元格(TableviewCell 和 CollectionViewCell)但无法按照我想要的方式获得它们。

我附上了我的ViewController 和 TableViewCell 类。请帮忙

struct Clothes 
var price: Double
var imgClUrl: String
var id: String
var isActive: Bool = true
var timeStamp: Timestamp
var stock: Double
var name: String
init(data : [String : Any]) 
    self.price = data["price"] as? Double ?? 0
    self.imgClUrl = data["imgClUrl"] as? String ?? ""
    self.id = data["id"] as? String ?? ""
    self.isActive = data["isActive"] as? Bool ?? true
    self.timeStamp = data["timeStamp"] as? Timestamp ?? Timestamp()
    self.stock = data["stock"] as? Double ?? 0
    self.name = data["name"] as? String ?? ""

struct TypesOfCLothing 
var title : String
var id : String
var clothes : [Clothes]
init (data : [String : Any])
    self.title = data["title"] as? String ?? ""
    self.id = data["id"] as? String ?? ""
    self.clothes = data["Clothes"] as! [Clothes]

class eachStoreTableViewCell: UITableViewCell

@IBOutlet weak var eachRowCollView: UICollectionView!

@IBOutlet weak var eachRowLbl: UILabel!


var clothes = [Clothes]()
override func awakeFromNib() 
    super.awakeFromNib()


    eachRowCollView?.reloadData()
    eachRowCollView?.delegate = self
    eachRowCollView?.dataSource = self
    self.eachRowCollView?.register(UINib(nibName: "RowColectionView", bundle: nil), forCellWithReuseIdentifier: Identifiers.ClothesCell)

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


func configureCell(clothingType: TypesOfCLothing) 
    eachRowLbl?.text = clothingType.title
extension eachStoreTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return clothes.count




func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Identifiers.ClothesCell, for: indexPath) as? RowColectionView
        cell.configureCell(clothes: clothes[indexPath.item])
        return cell
    
    return UICollectionViewCell()

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
    return CGSize(width: 160, height: 180)



class EachStoreVC: UIViewController 


@IBOutlet weak var StoreTblView: UITableView!

 var typesOfClothing = [TypesOfCLothing]()

var tienda: Tiendas!
let db = Firestore.firestore()
var listener : ListenerRegistration!
        override func viewDidLoad() 
        super.viewDidLoad()

  // StoreTblView?.delegate = self
   // StoreTblView?.dataSource = self
            StoreTblView?.register(UINib(nibName: "eachStoreTblViewCell", bundle: nil), forCellReuseIdentifier: Identifiers.ClothingTypeCell)
            StoreTblView?.cellLayoutMarginsFollowReadableWidth = false

override func viewDidAppear(_ animated: Bool) 


override func viewDidDisappear(_ animated: Bool) 



func numberOfSections(in tableView: UITableView) -> Int 
    return 1



extension EachStoreVC : UITableViewDelegate, UITableViewDataSource 
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return typesOfClothing.count

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    if let cell = tableView.dequeueReusableCell(withIdentifier: Identifiers.ClothingTypeCell, for: indexPath) as? eachStoreTableViewCell 
        cell.configureCell(clothingType: typesOfClothing[indexPath.row])
        cell.frame = CGRect(x: 0, y: 0, width: StoreTblView.frame.size.width, height: cell.frame.size.height)
        return cell
        
    return UITableViewCell()

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 

    return 200
 

编辑 collectionView 和 Tableview 现在显示正常,但我无法从 firebase 获取数据,我在每个 TypesOfClothing 文档中有一组文档引用,代码如下。我还更新了我的 2 个结构。

    func getRowData()
   listener = db.collection("TypesOfClothing").addSnapshotListener( (snap, error) in
        if let error = error 
            debugPrint(error.localizedDescription)
            return
        
        snap?.documentChanges.forEach( (change) in
            let data = change.document.data()
            let typesOfClothing = TypesOfCLothing.init(data: data)

            switch change.type 
                case.added:
                    self.onDocumentAdded(change: change, category: typesOfClothing)
                case.modified:
                    self.onDocumentModified(change: change, category: typesOfClothing)
                case.removed:
                    self.onDocumentRemoved(change: change)

            
        )

    )    


func onDocumentAdded(change: DocumentChange, category: TypesOfCLothing)
    let newIndex = Int(change.newIndex)
    typesOfClothing.insert(category, at: newIndex)
    StoreTblView?.insertRows(at: [IndexPath(row: newIndex, section: 0)], with: UITableView.RowAnimation.left)


func onDocumentModified(change: DocumentChange, category: TypesOfCLothing)
    if change.newIndex == change.oldIndex 
        let index = Int(change.newIndex)
        typesOfClothing[index] = category
        StoreTblView?.reloadRows(at: [IndexPath(row: index, section: 0)], with: UITableView.RowAnimation.left)

     else 
        let oldIndex = Int(change.oldIndex)
        let newIndex = Int(change.newIndex)
        typesOfClothing.remove(at: oldIndex)
        typesOfClothing.insert(category, at: newIndex)

        StoreTblView?.moveRow(at: IndexPath(row: oldIndex, section: 0), to: IndexPath(row: newIndex, section: 0))
    

func onDocumentRemoved(change: DocumentChange)
    let oldIndex = Int(change.oldIndex)
    typesOfClothing.remove(at: Int(oldIndex))
    StoreTblView?.deleteRows(at: [IndexPath(row: oldIndex, section: 0)], with: UITableView.RowAnimation.fade)

【问题讨论】:

【参考方案1】:

结构体使用如下:

struct TypesOfClothing 
   var title : String
   var clothes: [Clothes]



struct Clothes 
 var price: Double
 var imgClUrl: String
 var id: String
 var isActive: Bool = true
 var timeStamp: Timestamp
 var stock: Double
 var name: String

在主视图控制器中:尝试这样的代码:

var typesOfClothing: [TypesOfClothing] = []

in numberOfRowsInSection

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

    return typesOfClothing.count

在 cellForRowAt 中

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
     if let cell = tableView.dequeueReusableCell(withIdentifier: Identifiers.ClothingTypeCell, for: indexPath) as? eachStoreTableViewCell 

        if indexPath.row < typesOfClothing?.count ?? 0 
           let cellData = typesOfClothing?[indexPath.row]

           cell.configureCell(cellData)
        
       return cell
            
    return UITableViewCell()
  

在 UITableViewCell 类中尝试这样:

class eachStoreTableViewCell: UITableViewCell

   @IBOutlet weak var eachRowCollView: UICollectionView!

   @IBOutlet weak var eachRowLbl: UILabel!


   var clothes = [Clothes]()
   override func awakeFromNib() 
        super.awakeFromNib()

       eachRowCollView?.delegate = self
       eachRowCollView?.dataSource = self
       self.eachRowCollView?.register(UINib(nibName: "RowColectionView", bundle: nil), forCellWithReuseIdentifier: Identifiers.ClothesCell)
       
       override func setSelected(_ selected: Bool, animated: Bool) 
         super.setSelected(selected, animated: animated)
       

       func configureCell(_ clothingType: TypesOfClothing) 
        eachRowLbl?.text = clothingType.title
        clothes = clothingType.clothes 
        eachRowCollView?.reloadData()
         
     

   extension eachStoreTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
     return clothes.count
  


  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Identifiers.ClothesCell, for: indexPath) as? RowColectionView
    cell.configureCell(clothes: clothes[indexPath.item])
    return cell
    
     return UICollectionViewCell()
 
 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
return CGSize(width: 160, height: 180)
      
  

它会帮助你。

【讨论】:

为什么需要if indexPath.row &lt; typesOfClothing?.count ?? 0 用于检查衣服数据是否小于意味着它不会显示并防止数组索引越界 你在numberOfRowsInSection方法中使用了typesOfClothing.count。所以上面的检查是没有意义的 另外typesOfClothing 是非可选数组。像typesOfClothing?.count 这样的可选链接会抛出错误 好吧,如果该数组中的数据会频繁更改,那么检查索引是否越界总是更安全。如果您的阵列稳定且不会发生太大变化,那么您可以忽略该行。【参考方案2】:

您可以制作一个结构来加载 tableView 数据

struct ClothingData

   var typesOfClothing : String = ""
   var clothes : [Clothes] = []

为 tabelView 加载这个 structArray

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

    return ClothingData.count


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

    let cell = tableView.dequeueReusableCell(withIdentifier: Identifiers.ClothingTypeCell, for: indexPath) as? eachStoreTableViewCell

    let row = ClothingData[indexPath.row]

    cell.eachRowLbl?.text = row.typesOfClothing
    cell.clothes = row.clothes
    // Here you can pass clothesList to tabelViewCell for load collectionView
    return cell

【讨论】:

以上是关于获取 TableviewCells 以显示从 firebase 提取的不同数据并在 CollectionView 中显示它们的主要内容,如果未能解决你的问题,请参考以下文章

如何将两个(或更多)tableViewCells 添加在一起以形成“总数”

屏幕外(不可见)TableViewCells 不设置动画

我的 tableViewCells 没有创建?

正确隐藏和显示 TableViewCells?

searchBar 过滤 tableViewCells didSelectItemAt indexPath 显示在 navigationBar Title

快速,从具有 CustomCells 的 tableViewCells 中检索更改的数据