如何使 firebase 数据库数据成为 UICollectionView 的数据源?

how can I make firebase database data the data source for UICollection View?

我想将我的模型 object 数据源更改为 firebase。 我有一个文件用作 UI 集合视图 homeViewController.swift 的数据源。 homeViewController.swift 是一个垂直排列的 collectionViewCell,每个单元格都有自己水平排列的 collectionViewcell。

这是 models.swift 文件

import UIKit
import Firebase

class BusinessCategory: NSObject {

var name: String?
var featurebusiness: [SampleBusinesses]?
var type: String?


static func sampleBusinessCategories() -> [BusinessCategory] {
 let FastfoodCategory = BusinessCategory()
    FastfoodCategory.name = "Fast Food"
    var topFastFood = [SampleBusinesses]()

    let FastfoodApp = SampleBusinesses()
    FastfoodApp.name = "Papa Johns"
    FastfoodApp.imageName = "PJ"
    topFastFood.append(FastfoodApp)
    FastfoodCategory.featurebusiness = topFastFood


    let MobilePhoneCategory = BusinessCategory()
    MobilePhoneCategory.name = "Mobile Phones"
    var topMobilePhoneProvider = [SampleBusinesses]()
    //logic
    let MobilePhoneApp = SampleBusinesses()
    MobilePhoneApp.name = "Verizon"
    MobilePhoneApp.imageName = "verizon"
    topMobilePhoneProvider.append(MobilePhoneApp)
    MobilePhoneCategory.featurebusiness = topMobilePhoneProvider

    return [ FastfoodCategory, MobilePhoneCategory ]

我想更改 object 文件,以便它由我的 firebase 数据库 (BusinessCategories) 填充。我尝试了很多选择,但一直无法弄清楚。如何将我的 object 文件从物理输入的数据更改为 firebase 数据?

如果有帮助,这是我的 Firebase 数据。例如 "Banks" 将是类别名称,单元格将由银行下的所有条目填充。

更新: 我想要实现的是类似于 Appstore UI 的不同类别的应用程序,每个类别都是一个 collection 具有水平滚动的视图。在我的应用程序中,企业在 firebase 中列出了不同的类别,每个类别都可以水平滚动。

如何更新下面的 collection 视图属性?

 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CategoryCell

        cell.businessCategory = businessCategories?[indexPath.item]

    return cell
}

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    if let count = businessCategories?.count{

        return count 
    }
    return 0
}

我希望这能让您入门。拥有数据库的整个模式会更好,但我是根据我从您的屏幕截图中看到的内容制作的。似乎也不需要单独的 BusinessCategory 树,因为您在业务树中拥有每个业务的类别类型,尽管这完全取决于您。

如果您想提供更完整的数据库屏幕截图(仅显示键和数据类型),我很乐意修改此代码。

因为我不知道你是如何更新你的 collection 视图的,所以我已经做到了 returns 一个字典,其中键是类别,值是一组业务那个类别。如果您在 collection 视图中使用部分,这应该是一种简单的格式。

关于类型别名 FirebaseRootDictionary,它可能需要修改,因为我猜测您的数据库架构是什么。

如果您对此代码有任何疑问或问题,请在下方发表评论,我会尽力解决。

所以要获取您的数据:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    Business.getBusinesses { (businesses) in

        print(businesses)
    }
}

然后在闭包中更新 collection 视图。

import Foundation
import Firebase

final class Business : NSObject {

    typealias FirebaseRootDictionary = Dictionary<String,Dictionary<String,Dictionary<String,String>>>

    var name: String

    var category: String

    var email: String

    var imageUrl: String

    override var description: String {

        return "Business(name: \"\(name)\", category: \"\(category)\", email: \"\(email)\", imageUrl: \"\(imageUrl)\")"
    }

    init(name:String, category:String, email:String, imageUrl:String) {

        self.name = name

        self.category = category

        self.email = email

        self.imageUrl = imageUrl
    }

    class func getBusinesses(completionHandler:@escaping (_ businesses: BusinessesDictionary)->()) { // -> [Business]

        let ref = FIRDatabase.database().reference().child("BusinessCategories")

        var businesses = BusinessesDictionary()

        ref.observeSingleEvent(of: .value, with: { (snapshot) in

            guard let value = snapshot.value as? FirebaseRootDictionary else { return }

            let categories = value.keys.sorted()

            var arr = [Business]() // Array of businesses for category

            for cat in categories {

                guard let data = value[cat] else { continue }

                let businessKeys = data.keys.sorted()

                for key in businessKeys {

                    guard let businessData = data[key] else { continue }

                    guard let name = businessData["BusinessName"], let category = businessData["Category"], let email = businessData["email"], let imageUrl = businessData["imageUrl"] else { continue }

                    let business = Business(name: name, category: category, email: email, imageUrl: imageUrl)

                    arr.append(business)
                }

                businesses[cat] = arr

                arr.removeAll()
            }

            completionHandler(businesses)
        })
    }
}

编辑:

所以对于视图,您有一个 table视图,每个 section/category 有一个单元格。该单元格有一个 collection 视图,它有一个带有图像视图和标签的 collection 视图单元格。所以这里我有一个 table 视图控制器可以处理所有这些。

import UIKit

typealias BusinessesDictionary = Dictionary<String,[Business]> // I have moved this typealias to here instead of inside the Business Model.

class TableViewController: UITableViewController {

    var tableData = BusinessesDictionary()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.register(CategoryCell.self, forCellReuseIdentifier: "cell")

        self.tableView.allowsSelection = false

        Business.get { (businesses) in

            self.tableData = businesses

            self.tableView.reloadData()
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {

        return self.tableData.keys.count
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

        let category = self.tableData.keys.sorted()[section]

        return category
    }

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

        return 1
    }

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

        guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? CategoryCell else { return UITableViewCell() }

        // Configure the cell...

        let category = self.tableData.keys.sorted()[indexPath.section]

        guard let businesses = self.tableData[category] else { return UITableViewCell() }

        cell.businesses = businesses

        return cell
    }

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

        return 120
    }
}

table 查看单元格文件。

class CategoryCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {

    var collectionView: UICollectionView!

    var businesses = [Business]()

    override func layoutSubviews() {

        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()

        layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // You may wan to change this as this is the spacing between cells

        layout.itemSize = CGSize(width: 100, height: 120) // You may wan to change this as this is the cell size

        layout.scrollDirection = .horizontal

        collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: layout)

        collectionView.topAnchor.constraint(equalTo: self.topAnchor)

        collectionView.leftAnchor.constraint(equalTo: self.leftAnchor)

        collectionView.rightAnchor.constraint(equalTo: self.rightAnchor)

        collectionView.bottomAnchor.constraint(equalTo: self.bottomAnchor)

        collectionView.dataSource = self

        collectionView.delegate = self

        collectionView.register(BusinessCell.self, forCellWithReuseIdentifier: "businessCell")

        collectionView.backgroundColor = .white

        self.addSubview(collectionView)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        return businesses.count
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {

        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "businessCell", for: indexPath) as? BusinessCell else { return UICollectionViewCell() }

        // Configure the cell

        let business = self.businesses[indexPath.row]

        cell.nameLabel.text = business.name

        cell.imageView.image = UIImage(named: business.imageUrl)

        return cell
    }
}

这是 collection 视图单元格。

class BusinessCell: UICollectionViewCell {

    var imageView: UIImageView!

    var nameLabel: UILabel!

    override init(frame: CGRect) {
        super.init(frame: frame)

        imageView = UIImageView(frame: CGRect(x: 20, y: 20, width: 60, height: 60))

        imageView.contentMode = .scaleAspectFit

        nameLabel = UILabel(frame: CGRect(x: 0, y: 90, width: 100, height: 30))

        nameLabel.font = UIFont.systemFont(ofSize: 11)

        nameLabel.textAlignment = .center

        self.addSubview(imageView)

        self.addSubview(nameLabel)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

这里是我做的测试数据库的截图。