【问题标题】:Swift 5 - Firebase- create array from data in firebaseSwift 5 - Firebase - 从 firebase 中的数据创建数组
【发布时间】:2023-05-30 03:12:01
【问题描述】:

我正在尝试从我在 firebase 中的数据创建一个数组,以便我可以将它作为标题加载到我的 tableview 中。当我将信息硬编码在代码中的数组中时,我了解如何将数据放入节标题中,但是当数据在 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)
        }

【问题讨论】:

    标签: arrays swift firebase tableview nstableheadercell


    【解决方案1】:

    问题中没有提到用作部分标题的字符串,但根据之前的问题,我认为这些部分是事件日期。然后在该日期发生的事件将在该日期部分中列出。

    此答案中的代码未经测试,它只是众多选项之一。我还稍微改变了动态,将更多的责任放在 EventInfo 类逻辑中而不是循环中处理快照。

    首先,我们从一个保存事件详细信息的对象开始。注意它是用 Firebase Datasnapshot 初始化的。如果出现问题,它会利用选项的默认值。另请注意,我添加了一个 eventID 来跟踪 Firebase 键,以便以后可以通过该 id 更改或删除对象。

    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 数组来保存所有事件。这将用作节标题和 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()
        })
     }
    

    上面的代码一次读入所有的事件并且没有留下观察者。它遍历快照中的所有事件,为每个事件创建 EventObjects 并检查是否已经存在任何事件日期(该部分)。

    如果是,它添加到该部分日期数组的事件。

    如果没有,则创建一个新的 EventSectionHeader,设置日期并添加事件。

    【讨论】:

    • 感谢您的帮助,我收到一个错误,它不知道 evenSectionArray 是什么,因为我们引用了 eventArray?另外,当我在我的 EventsInfo 中执行 eventSnap 时,它说转换为不相关的类型 String 总是会失败
    • @MattyJay94 那将是您的 tableView 数据源数组 - 请参阅您之前的问题和我的回答 here。而在 EventIInfo init 中,这些应该是 .value。现在修复。阅读 Firebase 入门指南 Reading Data 对您很有帮助
    • 好的,我在发布回复后立即找到了 .Value,但谢谢。在更多地使用 Firebase 之前,我也会查看该指南。
    • 所以日期正在加载到标题单元格中,但我的标题没有加载到它下面。它只是堆叠日期。我收到一个警告,我应该在 eventArray 上将 var 更改为 let,因为它没有发生变异。
    • var eventArray = [EventInfo]() 中的 getEventsFromFirebaseDB 是一个错字。它被注释掉了。变异意味着改变,没有代码改变那个数组。