Swift 5- Firebase- 按 header 中的日期分组
Swift 5- Firebase- Group by date in header
我的主要目标是从 Firebase 数据库中获取日期并将其用作一个部分 header 以便我可以加载具有相同日期的所有事件 header。
我希望它像这样显示在我的 table 视图中:
9 月 -header
-2020-09-29 -sub header
--事件
--事件
--事件
-2020 年 9 月 30 日 -sub header
--事件
--事件
--事件
这是我的主视图控制器。
import UIKit
import Foundation
import Firebase
import FirebaseDatabase
class EventsTableViewController: UIViewController {
var sectionNames: [String] = []
var events: [String: [EventsInfo]] = [:]
var datref: DatabaseReference!
var eventView = [EventsInfo]()
@IBOutlet weak var eventTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
getEventsFromFirebaseDB()
}
deinit {
datref.removeAllObservers()
}
private func eventsFetched(_ eventData: [EventsInfo])
{
for event in eventData
{
guard let eventNameFirstChar = event.date.first else { continue }
if var eventsForKey = events["\(eventNameFirstChar)"]
{
eventsForKey.append(event)
events["\(eventNameFirstChar)"] = eventsForKey
}
else
{
// no users are stored in dictionary for key userNameFirstChar
events["\(eventNameFirstChar)"] = [event]
}
}
// sort dictionary keys and set it in sectionNames
sectionNames = events.map { [=12=].key }.sorted()
print (sectionNames)
}
private func getEventsFromFirebaseDB() {
datref = Database.database().reference().child("events")
datref.observe(DataEventType.value, with: { [weak self] (snapshot) in
guard snapshot.childrenCount > 0 else { return }
var events: [EventsInfo] = []
for event in snapshot.children.allObjects as! [DataSnapshot]
{
let object = event.value as? [String: AnyObject]
let title = object?["title"]
let place = object?["place"]
let info = object?["info"]
let date = object?["date"]
let time = object?["time"]
let event = EventsInfo(title: title as! String, place: place as! String, info: info as! String, time: time as! String, date: date as! String)
events.append(event)
}
self?.eventsFetched(events)
self?.eventTableView.reloadData()
})
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showEvent"
{
if let indexPath = eventTableView.indexPathForSelectedRow
{
let destinationController = segue.destination as! EventsInfoViewController
let char = sectionNames[indexPath.section]
let event = events[char]![indexPath.row]
destinationController.EventsData = event
}
}
}
}
extension EventsTableViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
sectionNames.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
sectionNames[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let char = sectionNames[section]
return events[char]!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = eventTableView.dequeueReusableCell(withIdentifier: "eventsCell") as! EventsTableViewCell
let char = sectionNames[indexPath.section]
let event = events[char]![indexPath.row]
cell.eventTitleLabel.text = event.title
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showEvent", sender: self)
}
这是我的 EventsInfo 文件
import Foundation
class EventsInfo {
var title: String
var place: String
var info: String
var time: String
var date: String
init(title: String, place: String, info: String, time: String, date: String) {
self.title = title
self.place = place
self.info = info
self.time = time
self.date = date
}
}
我正在抛出一个答案,希望它能通过示例提供一些方向。请注意,其中 none 与 Firebase 有关 - 它纯粹是 tableView 管理。
我们的应用程序是一个水果列表,部分标题是每个水果的名字
A
Apple
B
Banana
等等
这是一个结构来保存每个部分的数据,然后是一个 class 数组来保存那些 objects(tableView 数据源)
struct FruitStruct {
var sectionTitle = ""
var fruitNameArray = [String]()
}
var fruitDataSource = [FruitStruct]()
然后让我们填充该数据
func setupDataSourceData() {
let fruitArray = ["Apple", "Pear", "Banana", "Bing Cherry", "Grape", "Orange", "Plum", "Watermelon", "Cantelope"]
let allFirstChars = fruitArray.map { String([=12=].prefix(1)) } //get all first chars for section titles
let sectionTitles = Array(Set(allFirstChars)).sorted() //eliminate dups and sort
//iterate over the unique section titles and get the fruits that are in that section
// sort and then craft structs to hold the title and the associated fruits
sectionTitles.forEach { firstChar in
let results = fruitArray.filter { [=12=].prefix(1) == firstChar }
let sortedFruits = results.sorted()
let fruit = FruitStruct(sectionTitle: firstChar, fruitNameArray: sortedFruits)
fruitDataSource.append(fruit)
}
//this code is to just output the data to console so you can see what it
// looks like. Remove it.
for fruitData in fruitDataSource {
print(fruitData.sectionTitle)
let fruits = fruitData.fruitNameArray
for fruitName in fruits {
print(" \(fruitName)")
}
}
}
最后,tableView 委托方法从数据源填充 tableView
//
//handle sections
//
func numberOfSections(in tableView: UITableView) -> Int {
return self.fruitDataSource.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let title = self.fruitDataSource[section].sectionTitle
return title
}
//
//handleTableView rows
//
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let rowsInSection = self.fruitDataSource[section].fruitNameArray.count
return rowsInSection
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)
let text = self.fruitDataSource[indexPath.section].fruitNameArray[indexPath.row]
cell.textLabel?.text = text
return cell
}
我的主要目标是从 Firebase 数据库中获取日期并将其用作一个部分 header 以便我可以加载具有相同日期的所有事件 header。
我希望它像这样显示在我的 table 视图中:
9 月 -header
-2020-09-29 -sub header
--事件
--事件
--事件
-2020 年 9 月 30 日 -sub header
--事件
--事件
--事件
这是我的主视图控制器。
import UIKit
import Foundation
import Firebase
import FirebaseDatabase
class EventsTableViewController: UIViewController {
var sectionNames: [String] = []
var events: [String: [EventsInfo]] = [:]
var datref: DatabaseReference!
var eventView = [EventsInfo]()
@IBOutlet weak var eventTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
getEventsFromFirebaseDB()
}
deinit {
datref.removeAllObservers()
}
private func eventsFetched(_ eventData: [EventsInfo])
{
for event in eventData
{
guard let eventNameFirstChar = event.date.first else { continue }
if var eventsForKey = events["\(eventNameFirstChar)"]
{
eventsForKey.append(event)
events["\(eventNameFirstChar)"] = eventsForKey
}
else
{
// no users are stored in dictionary for key userNameFirstChar
events["\(eventNameFirstChar)"] = [event]
}
}
// sort dictionary keys and set it in sectionNames
sectionNames = events.map { [=12=].key }.sorted()
print (sectionNames)
}
private func getEventsFromFirebaseDB() {
datref = Database.database().reference().child("events")
datref.observe(DataEventType.value, with: { [weak self] (snapshot) in
guard snapshot.childrenCount > 0 else { return }
var events: [EventsInfo] = []
for event in snapshot.children.allObjects as! [DataSnapshot]
{
let object = event.value as? [String: AnyObject]
let title = object?["title"]
let place = object?["place"]
let info = object?["info"]
let date = object?["date"]
let time = object?["time"]
let event = EventsInfo(title: title as! String, place: place as! String, info: info as! String, time: time as! String, date: date as! String)
events.append(event)
}
self?.eventsFetched(events)
self?.eventTableView.reloadData()
})
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showEvent"
{
if let indexPath = eventTableView.indexPathForSelectedRow
{
let destinationController = segue.destination as! EventsInfoViewController
let char = sectionNames[indexPath.section]
let event = events[char]![indexPath.row]
destinationController.EventsData = event
}
}
}
}
extension EventsTableViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
sectionNames.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
sectionNames[section]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let char = sectionNames[section]
return events[char]!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = eventTableView.dequeueReusableCell(withIdentifier: "eventsCell") as! EventsTableViewCell
let char = sectionNames[indexPath.section]
let event = events[char]![indexPath.row]
cell.eventTitleLabel.text = event.title
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showEvent", sender: self)
}
这是我的 EventsInfo 文件
import Foundation
class EventsInfo {
var title: String
var place: String
var info: String
var time: String
var date: String
init(title: String, place: String, info: String, time: String, date: String) {
self.title = title
self.place = place
self.info = info
self.time = time
self.date = date
}
}
我正在抛出一个答案,希望它能通过示例提供一些方向。请注意,其中 none 与 Firebase 有关 - 它纯粹是 tableView 管理。
我们的应用程序是一个水果列表,部分标题是每个水果的名字
A
Apple
B
Banana
等等
这是一个结构来保存每个部分的数据,然后是一个 class 数组来保存那些 objects(tableView 数据源)
struct FruitStruct {
var sectionTitle = ""
var fruitNameArray = [String]()
}
var fruitDataSource = [FruitStruct]()
然后让我们填充该数据
func setupDataSourceData() {
let fruitArray = ["Apple", "Pear", "Banana", "Bing Cherry", "Grape", "Orange", "Plum", "Watermelon", "Cantelope"]
let allFirstChars = fruitArray.map { String([=12=].prefix(1)) } //get all first chars for section titles
let sectionTitles = Array(Set(allFirstChars)).sorted() //eliminate dups and sort
//iterate over the unique section titles and get the fruits that are in that section
// sort and then craft structs to hold the title and the associated fruits
sectionTitles.forEach { firstChar in
let results = fruitArray.filter { [=12=].prefix(1) == firstChar }
let sortedFruits = results.sorted()
let fruit = FruitStruct(sectionTitle: firstChar, fruitNameArray: sortedFruits)
fruitDataSource.append(fruit)
}
//this code is to just output the data to console so you can see what it
// looks like. Remove it.
for fruitData in fruitDataSource {
print(fruitData.sectionTitle)
let fruits = fruitData.fruitNameArray
for fruitName in fruits {
print(" \(fruitName)")
}
}
}
最后,tableView 委托方法从数据源填充 tableView
//
//handle sections
//
func numberOfSections(in tableView: UITableView) -> Int {
return self.fruitDataSource.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let title = self.fruitDataSource[section].sectionTitle
return title
}
//
//handleTableView rows
//
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let rowsInSection = self.fruitDataSource[section].fruitNameArray.count
return rowsInSection
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier", for: indexPath)
let text = self.fruitDataSource[indexPath.section].fruitNameArray[indexPath.row]
cell.textLabel?.text = text
return cell
}