Swift 5- Firebase- Group by date in header

孤街醉人 提交于 2021-01-29 05:15:34

问题


My Main goal is to take the Date from the Firebase Database and use is as a section header so that i may load all the events that have the same date under that header.

I would like it to appear in my table view like this:

September -header

-September 29,2020 -sub header

--event

--event

--event

-september 30, 2020 -sub header

--event

--event

--event

This is my main View Controller.

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 { $0.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)
    }

This is my EventsInfo File


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

    }
}


回答1:


I am tossing out an answer in hopes it will provide some direction though an example. Note that none of this is related to Firebase - it's purely tableView management.

Our app is a list is fruits with section titles being the first name of each fruit

A
   Apple
B
   Banana

etc

Here's a struct to hold each section's data and then a class array to hold those objects (the tableView dataSource)

struct FruitStruct {
   var sectionTitle = ""
   var fruitNameArray = [String]()
}

var fruitDataSource = [FruitStruct]()

then let's populate that data

func setupDataSourceData() {
    let fruitArray = ["Apple", "Pear", "Banana", "Bing Cherry", "Grape", "Orange", "Plum", "Watermelon", "Cantelope"]

    let allFirstChars = fruitArray.map { String($0.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 { $0.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)")
        }
    }
}

lastly, the tableView delegate methods to populate the tableView from the dataSource

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


来源:https://stackoverflow.com/questions/64139298/swift-5-firebase-group-by-date-in-header

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!