使用Firebase数据库和存储下载数据时,索引超出范围异常

时间:2019-02-14 18:22:47

标签: swift firebase firebase-realtime-database firebase-storage asyncdisplaykit

这是我的方法,用于检索用户数组并从数据库中发布对象。

func getRecentPost(start timestamp: Int? = nil, limit: UInt, completionHandler: @escaping ([(Post, UserObject)]) -> Void) {

    var feedQuery = REF_POSTS.queryOrdered(byChild: "timestamp")
    if let latestPostTimestamp = timestamp, latestPostTimestamp > 0 {
        feedQuery = feedQuery.queryStarting(atValue: latestPostTimestamp + 1, childKey: "timestamp").queryLimited(toLast: limit)
    } else {
        feedQuery = feedQuery.queryLimited(toLast: limit)
    }

    // Call Firebase API to retrieve the latest records
    feedQuery.observeSingleEvent(of: .value, with: { (snapshot) in
        let items = snapshot.children.allObjects

        let myGroup = DispatchGroup()

        var results: [(post: Post, user: UserObject)] = []

        for (index, item) in (items as! [DataSnapshot]).enumerated() {
            myGroup.enter()
            Api.Post.observePost(withId: item.key, completion: { (post) in
                Api.User.observeUser(withId: post.uid!, completion: { (user) in
                    results.insert((post, user), at: index) //here is where I get my error -> Array index is out of range
                    myGroup.leave()
                })
            })
        }
        myGroup.notify(queue: .main) {
            results.sort(by: {$0.0.timestamp! > $1.0.timestamp! })
            completionHandler(results)
        }
    })

}

这是我的视图控制器对方法的调用。我目前正在使用纹理用户界面来帮助实现更快,更流畅的用户界面。

var firstFetch = true
func fetchNewBatchWithContext(_ context: ASBatchContext?) {
    if firstFetch {
        firstFetch = false
        isLoadingPost = true
        print("Begin First Fetch")
        Api.Post.getRecentPost(start: posts.first?.timestamp, limit: 8  ) { (results) in
            if results.count > 0 {
                results.forEach({ (result) in
                    posts.append(result.0)
                    users.append(result.1)
                })
            }
            self.addRowsIntoTableNode(newPhotoCount: results.count)
            print("First Batch Fetched")
            context?.completeBatchFetching(true)
            isLoadingPost = false
            print("First Batch", isLoadingPost)
        }

    } else {
        guard !isLoadingPost else {
            context?.completeBatchFetching(true)
            return
        }
        isLoadingPost = true

        guard let lastPostTimestamp = posts.last?.timestamp else {
            isLoadingPost = false
            return
        }
        Api.Post.getOldPost(start: lastPostTimestamp, limit: 9) { (results) in
            if results.count == 0 {
                return
            }
            for result in results {
                posts.append(result.0)
                users.append(result.1)
            }
            self.addRowsIntoTableNode(newPhotoCount: results.count)
            context?.completeBatchFetching(true)
            isLoadingPost = false
            print("Next Batch", isLoadingPost)

        }
    }


}

在代码的第一部分中,我进行了调试,以查看是否可以了解正在发生的情况。当前,firebase返回的是我将查询限制为(8)的对象的正确数量。但是,在我突出显示发生错误的地方,当索引将要插入第五个对象时,索引会跳转,index [3]->第四个对象在数组中,到要解析的index [7]->第五个对象,在解析第5个对象时插入。

因此,它不是从index [3]转到index [4],而是跳转到index [7]。 有人可以帮助我了解发生了什么以及如何解决吗?

1 个答案:

答案 0 :(得分:0)

for循环在其线程上继续,而observeUserobservePost回调在其他线程上。查看您的代码,您可能可以将appending对象而不是results移到inserting数组中。这是有道理的,因为无论如何您都在for循环之后进行排序,所以顺序为什么重要?