表刷新指数超出范围?

时间:2017-03-01 22:10:21

标签: ios swift uitableview firebase firebase-realtime-database

当用户下拉时,我为tableView添加了刷新功能。这大部分时间都有效,但偶尔会出现致命错误,Index超出范围。调用刷新表的回调执行以下操作: 1)清空数据结构,保存要显示的数据 2)从Firebase数据库中获取数据 3)将数据解析为单个部分并插入数据结构中 4)刷新表格 但是,在我的tableView的cellForRowAt indexPath函数中,我在函数的第一行得到致命错误: let eventsOnDay = eventsForDate [allDates [indexPath.section]]! 这是我的刷新回调代码: var allDates = [DateStruct]()//保存事件的所有唯一日期 var eventsForDate = [DateStruct:[PetEvent]]()//保存每一天的所有事件 ///从db读取事件,拆分为各个日期 /// func readEventsFromDb(){  // 1.清空数据结构         eventsForDate.removeAll()         allDates.removeAll()         让dbRef = FIRDatabase.database()。reference()。child(" pets")。child(currentPet).child(" events")  // 2.从db中获取数据         dbRef.observeSingleEvent(of:。value,with:{snapshot in             如果让snapshots = snapshot.children.allObjects为? [FIRDataSnapshot] {  // 3.将数据拆分为单个组件                 用于快照中的子项{                     如果让data = child.value为? [String:Any] {                         如果让c = data [" comment"]为?字符串,让p =数据["用户"]为?字符串,让t =数据["类型"]为? Int,让d =数据[" date"]为? UInt64 {                             let event = PetEvent(comment:c,person:p,type:t,time:self.timeFromEpoch(time:Double(d)))                             let eventDate = self.dateFromEpoch(time:Double(d))                             if(self.eventsForDate [eventDate]!= nil){                                 self.eventsForDate [EVENTDATE]!追加(事件)                             } else {                                 self.eventsForDate [eventDate] = [event]                             }                         }                     }                 }                 self.allDates = Array(self.eventsForDate.keys).sorted {d1,d2 in                     d2< D1                 }  // 4.重新加载表格                 self.feedTable.reloadData()                 self.refreshControl.endRefreshing()             }         })     } 我很难搞清楚为什么大部分时间都在工作,但偶尔会失败。有没有人有想法?

3 个答案:

答案 0 :(得分:2)

如果你的目标是避免崩溃,你可以通过这样的方式安全地检查你的eventOnDelay项目:

if allDates.count > indexPath.section {
    guard let eventsOnDay = eventsForDate[allDates[indexPath.section]] else {
        //handle error here...
        return
    }
    //Do whatever you need with eventsOnDay here
} else {
    //Check your numberOfSections method, as it's not set up correctly
}

您还必须确保在主线程上调用tableView.reloadData()endRefreshing,因为您的Firebase回调可能会在bg主题上回传。

答案 1 :(得分:1)

您可以使用不同的方法来更新表格视图内容。我认为从使用回调dbRef.observeSingleEvent的firebase获取数据有延迟。您将在函数调用开始时删除以前的数据。您可以尝试以下两种方法来解决问题

1。删除dbRef.observeSingleEvent回调

中的空数据
var allDates = [DateStruct]() // Holds all unique dates of events
var eventsForDate = [DateStruct : [PetEvent]]()  // Holds all events for each day

//  Read events from db, split into individual dates
func readEventsFromDb() {
let dbRef = FIRDatabase.database().reference().child("pets").child(currentPet).child("events")
// 1. Fetch data from db
 dbRef.observeSingleEvent(of: .value, with: { snapshot in
 if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
 // 2. Empty out data structures
  eventsForDate.removeAll()
  allDates.removeAll()
  // 3. Split data into individual components
  for child in snapshots{
                if let data = child.value as? [String: Any] {
                    if let c = data["comment"] as? String, let p = data["user"] as? String, let t = data["type"] as? Int, let d = data["date"] as? UInt64 {
                        let event = PetEvent(comment: c, person: p, type: t, time: self.timeFromEpoch(time: Double(d)))
                        let eventDate = self.dateFromEpoch(time: Double(d))
                        if (self.eventsForDate[eventDate] != nil) {
                            self.eventsForDate[eventDate]!.append(event)
                        } else {
                            self.eventsForDate[eventDate] = [event]
                        }
                    }
                }
            }
            self.allDates = Array(self.eventsForDate.keys).sorted {d1,d2 in
                d2 < d1
            }
 // 4. Check if this is on UI/Main thread. Reload table
            self.feedTable.reloadData()
            self.refreshControl.endRefreshing()
        }
    })
}

2。使用临时数组来保存数据,然后使用临时数组

更新主数据
//Read events from db, split into individual dates
func readEventsFromDb() {
    let dbRef = FIRDatabase.database().reference().child("pets").child(currentPet).child("events")
  // 1. Fetch data from db
    dbRef.observeSingleEvent(of: .value, with: { snapshot in
        if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot]       {
        var tempAllDates = [DateStruct]()   // Holds all unique dates of events
        var tempEventsForDate = [DateStruct : [PetEvent]]()
   // 2. Split data into individual components
            for child in snapshots{
                if let data = child.value as? [String: Any] {
                    if let c = data["comment"] as? String, let p = data["user"] as? String, let t = data["type"] as? Int, let d = data["date"] as? UInt64 {
                        let event = PetEvent(comment: c, person: p, type: t, time: self.timeFromEpoch(time: Double(d)))
                        let eventDate = self.dateFromEpoch(time: Double(d))
                        if (self.tempEventsForDate[eventDate] != nil) {
                            self.tempEventsForDate[eventDate]!.append(event)
                        } else {
                            self. tempEventsForDate[eventDate] = [event]
                        }
                    }
                }
            }
            self. tempAllDates = Array(self.eventsForDate.keys).sorted {d1,d2 in
                d2 < d1
            }
    // 3. Empty out data structures
           eventsForDate.removeAll()
        allDates.removeAll()

    // 4. Fill data with temporary array. check the size 
        if tempEventsForDate.count > 0{
            eventsForDate = tempEventsForDate 
        }
        if tempAllDates.count > 0{
            allDates =  tempAllDates
        }

   // 5. Check if this is on UI/Main thread. Reload table
            self.feedTable.reloadData()
            self.refreshControl.endRefreshing()
        }
    })
}

希望这种方法有助于解决问题:)

答案 2 :(得分:1)

检查数组(包含要显示的数据)在tableview的委托和数据源方法中是否为空。

即。在cellForRow方法

 check if(yourArray.count > 0){
      // Do your code
   }
 else{
     // Dont
  }