如何使Firebase数据库数据成为UICollection View的数据源? [英] how can I make firebase database data the data source for UICollection View?

查看:132
本文介绍了如何使Firebase数据库数据成为UICollection View的数据源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这是models.swift文件

 导入UIKit 
导入Firebase

class BusinessCategory:NSObject {

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


static func sampleBusinessCategories() - > [商业类别] {
让FastfoodCategory = BusinessCategory()
FastfoodCategory.name =快餐
var topFastFood = [SampleBusinesses]()

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


让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] ​​

我想更改目标文件,由我的firebase数据库(BusinessCategories)。我已经尝试了很多选择,但是我一直无法弄清楚。如何将我的对象文件从实际输入的数据更改为Firebase数据?



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



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



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

  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
}

覆盖func collectionView(_ collectionView: UICollectionView,numberOfItemsInSection部分:Int) - > Int {
if let count = businessCategories?.count {

return count
}
return 0
}
解决方案

我希望这会让你开始。拥有数据库的整个模式会更好,但是我已经根据我从屏幕截图中可以看到的内容做出了这一点。也似乎有一个单独的BusinessCategory树不需要,因为你有业务树中的每个业务的类别类型,虽然这完全取决于你自己。



如果你想提供一个更完整的数据库截图(只是显示键和数据类型的东西),我很乐意修改这个代码。



因为我不不知道你如何更新你的集合视图,我已经做了它,所以它返回一个字典,其中的关键是类别,价值是该类别的bussinesses数组。这应该是一个简单的格式,如果您在集合视图中使用部分。

关于typealias FirebaseRootDictionary,它可能需要修改,因为我猜测什么是什么您的数据库模式是。



如果您对此代码有任何问题或疑问,请在下面留言,我会尽力解决。

b
$ b

所以得到你的数据:
$ b $ pre $ override func viewDidLoad(){
super.viewDidLoad()
//加载视图后,通常从一个笔尖执行任何额外的设置。

Business.getBusinesses {(business)in
$ b print(business)
}
}

然后在那个闭包里面更新集合视图。

  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

覆盖var description:String {

returnBusiness(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
$ b self.imageUrl = imageUrl
}
$ b $ class func getBusinesses(completionHandler:@escaping(_ business:BusinessesDictionary) - >()){ / - > [Business]

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

var business = BusinessesDictionary()

ref.observeSingleEvent(:.value,其中:{(snapshot)in

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

let categories = value.keys.sorted()

var arr = [Business]()//类别为

的商家数组{b
$ b guard让data = value [cat] else {continue}

让businessKeys = data.keys.sorted()

作为businessKeys中的键{

guard让businessData = data [key] else {continue}
$ b $ guard let let name = businessData [BusinessName],let category = businessData [Category],let email = businessData [电子邮件],让imageUrl = businessData [imageUrl]否则(继续)

让商业=商业(名称:名称,类别:类别,电子邮件:电子邮件,imageUrl:imageUrl)

arr.append(业务)
}







$ b $完成处理器(企业)
} )




$ b编辑:

所以对于视图来说,每个section / category有一个单元格的tableview。单元格有一个集合视图,它具有一个带有图像视图和标签的集合视图单元。所以在这里我有一个表视图控制器,将处理所有这些。

  import UIKit 

typealias BusinessesDictionary =词典<字符串,[商业]> //我把这个typealias移到了这里,而不是在商业模型里面。

TableViewController:UITableViewController {

var tableData = BusinessesDictionary()

重写func viewDidLoad(){
super.viewDidLoad()

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

self.tableView.allowsSelection = false

Business.get {(business)in

self.tableData = business

self.tableView.reloadData()
}
}

重写func didReceiveMemoryWarning(){
super.didReceiveMemoryWarning()
//处理任何可以重新创建的资源。

$ b // MARK: - 表视图数据源

重写func numberOfSections(在tableView:UITableView中) - > Int {

返回self.tableData.keys.count
}

覆盖func tableView(_ tableView:UITableView,titleForHeaderInSection section:Int) - >串? {

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

返回类别
}

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

return 1
}

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

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

//配置单元...

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

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

cell.businesses = business

return cell
}

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

return 120
}
}


$ b

  class CategoryCell:UITableViewCell,UICollectionViewDelegate,UICollectionViewDataSource {

var collectionView :UICollectionView!

var business = [商业]()
$ b重写func layoutSubviews(){

布局:UICollectionViewFlowLayout = UICollectionViewFlowLayout()

layout.sectionInset = UIEdgeInsets(top:0,left:0,bottom:0,right:0)//你可能会改变这个,因为这是单元格之间的间距

layout .itemSize = CGSize(width:100,height:120)//你可能会改变这个,因为这是单元大小

layout.scrollDirection = .horizo​​ntal

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 =。白色

self.addSubview(collectionView)
}

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

return business.count
}

func numberOfSections(在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()}

//配置单元格

let business = self.businesses [indexPath.row]

cell。 nameLabel.text = business.name

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

return cell
}
}

这是集合视图单元。

  class BusinessCell:UICollectionViewCell {

var imageView:UIImageView!

var nameLabel:UILabel!

覆盖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)
}

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


I want to change my model object datasource to firebase. I have a file that serves as the datasource for the UICollection view, homeViewController.swift . homeViewController.swift is a vertically arranged collectionViewCell and each cell has its own horizontally arranged collectionViewcell.

This is the models.swift file

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 ]

I want to change the object file so that it is populated by my firebase database (BusinessCategories). I have tried many options but I have not been able to figure it out. How do I change my object file from the physically entered data to firebase data?

Here is my Firebase data if it helps. For example "Banks" will be category name and the cell will be populated by all the entries under banks.

Update: What I am trying to achieve is similar to Appstore UI that different categories of apps and each category is a collection view with an horizontal scroll. In my application, Businesses are in different categories listed in firebase and each category is scrollable horizontally.

how do I update my collection view attributes below?

 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
}

解决方案

I hope this will get you started. It would be better to have the whole schema of the database, but I have made this based on what I could see from your screenshot. It also seems that having a separate BusinessCategory tree is not needed since you have the category type for each business in the Business tree, although that is completely up to you.

If you want to provide a more complete screenshot of your database (just something that shows the keys and data types), I would be happy to modify this code.

Since I don't know how you update your collection view, I have made it so it returns a Dictionary where the key is the category and the value is an array of bussinesses of that category. This should be an easy format if you are using sections in your collection view.

With regards to the typealias FirebaseRootDictionary, it might need to be modified as I was guessing on what your database schema was.

If you have any questions or problems with this code just put a comment beneath, and I'll try to fix it.

So to get your data:

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

    Business.getBusinesses { (businesses) in

        print(businesses)
    }
}

Then inside that closure have it update the collection view.

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

Edit:

So for the view, you have a tableview with one cell per section/category. The cell has a collection view, which has a collection view cell with a image view and label. So here I have a table view controller that will handle all that.

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

The table view cell file.

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

This is the collection view cell.

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

Here is a screenshot of the test database I made.

这篇关于如何使Firebase数据库数据成为UICollection View的数据源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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