Swift 5 - Firebase- создать массив из данных в firebase

Я пытаюсь создать массив из моих данных в firebase, чтобы я мог загрузить его в качестве заголовка в моем табличном представлении. Я понимаю, как поместить данные в заголовки разделов, когда у меня есть информация, жестко закодированная в массиве кода, но я не уверен, как это сделать, когда данные находятся в Firebase, и я хочу поместить это в массив, а затем поместите это в заголовки. Надеюсь, это имеет смысл.

мои данные Firebase

usclmainmenu
    events
        USCL Open House
           date: 
              "September 31 2020"
           info: 
              "Opening to new students"
           place: 
              "USC Lancaster"
           time: 
              "8 pm"
           title: 
               "USCL Open House"

Моя функция для получения данных из firebase:

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

          
        }


Моя модель данных:

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

    }
}

Это мое расширение для моих методов источника данных и делегата

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

1 ответ

Решение

Строка, которая будет использоваться в качестве заголовков разделов, не упоминалась в вопросе, но, исходя из предыдущего вопроса, я считаю, что разделы должны быть датами событий. Затем события, которые происходят в этот день, должны быть перечислены в этом разделе даты.

Код в этом ответе не проверен, и это только один из многих вариантов. Я также немного изменил динамику и возложил больше ответственности за обработку снимков в логику класса EventInfo, а не на цикл.

Во-первых, мы начинаем с объекта для хранения деталей события. Отмечая, что он инициализирован снимком данных Firebase. В случае, если что-то пойдет не так, он использует значения по умолчанию для опций. Также обратите внимание, что я добавил идентификатор события, который отслеживает ключ Firebase, поэтому объект можно позже изменить или удалить с помощью этого идентификатора.

class EventInfo {
    var eventId: String
    var title: String
    var place: String
    var date: String
    
    init(eventSnap: DataSnapshot) {
        self.eventId = eventSnap.key
        self.title = eventSnap.childSnapshot(forPath: "title").value as? String ?? "No Title"
        self.place = eventSnap.childSnapshot(forPath: "title").value as? String ?? "No Place"
        self.date = eventSnap.childSnapshot(forPath: "date").value as? String ?? "Unknown Date"
    }
}

затем массив var class для хранения всех событий. Это будет работать как источник данных для заголовков разделов и данных tableView.

class EventSectionHeader {
    var eventDate = ""
    var eventArray = [EventInfo]()
}

затем класс var для хранения всех заголовков EventSectionHeaders

var eventSectionArray = [EventSectionHeader]()

Наконец, код для чтения этих данных и заполнения источника данных.

func getEventsFromFirebaseDB() {
    //var eventArray = [EventInfo]()
    let eventRef = Database.database().reference().child("events")
    eventRef.observeSingleEvent(of: .value, with: { snapshot in
        let allEventSnaps = snapshot.children.allObjects as! [DataSnapshot]
        for eventSnap in allEventSnaps {
            let event = EventInfo(eventSnap: eventSnap)
            
            if let foundEventSection = self.eventSectionArray.first(where: { $0.eventDate == event.date } ) {
                foundEventSection.eventArray.append(event) //found same date, add event
            } else { //eventSection with this date doesn't exist, add a new section with this date and add this
                     //  event to that new section
                let eventSection = EventSectionHeader()
                eventSection.eventDate = event.date
                self.eventSectionArray.append(eventSection)
            }
        }
        
        self.tableView.reloadData()
    })
 }

Приведенный выше код считывает все события один раз и не оставляет наблюдателя. Он выполняет итерацию по всем событиям в снимке, создавая объекты EventObject для каждого и проверяя, существуют ли какие-либо даты событий (раздел).

Если да, то событие, которое он добавил в массив дат раздела.

Если нет, создается новый заголовок EventSectionHeader, устанавливается дата и добавляется событие.

Другие вопросы по тегам