如何使Firebase数据库数据成为UICollection View的数据源? [英] how can I make firebase database data the data source for 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
}
$ c 解决方案
我希望这会让你开始。拥有数据库的整个模式会更好,但是我已经根据我从屏幕截图中可以看到的内容做出了这一点。也似乎有一个单独的BusinessCategory树不需要,因为你有业务树中的每个业务的类别类型,虽然这完全取决于你自己。
如果你想提供一个更完整的数据库截图(只是显示键和数据类型的东西),我很乐意修改这个代码。
因为我不不知道你如何更新你的集合视图,我已经做了它,所以它返回一个字典,其中的关键是类别,价值是该类别的bussinesses数组。这应该是一个简单的格式,如果您在集合视图中使用部分。
关于typealias FirebaseRootDictionary,它可能需要修改,因为我猜测什么是什么您的数据库模式是。
如果您对此代码有任何问题或疑问,请在下面留言,我会尽力解决。
b$ b
所以得到你的数据: 然后在那个闭包里面更新集合视图。 所以对于视图来说,每个section / category有一个单元格的tableview。单元格有一个集合视图,它具有一个带有图像视图和标签的集合视图单元。所以在这里我有一个表视图控制器,将处理所有这些。 这是集合视图单元。 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 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?
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: Then inside that closure have it update the collection view. 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. The table view cell file. This is the collection view cell. Here is a screenshot of the test database I made. 这篇关于如何使Firebase数据库数据成为UICollection View的数据源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
$ b $ pre $
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编辑:
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 = .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 =。白色
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)
}
}
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 ]
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
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
Business.getBusinesses { (businesses) in
print(businesses)
}
}
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)
})
}
}
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
}
}
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
}
}
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)
}
}