Исключение индекса вне диапазона при использовании базы данных и хранилища firebase для загрузки данных - PullRequest
0 голосов
/ 14 февраля 2019

Вот мой метод получения массива пользовательских и публикуемых объектов из базы данных.

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).Но там, где я выдвинул на первый план ошибку, происходит скачок индекса, когда он собирается вставить пятый объект, индекс [3] -> 4-й объект находится в массиве, чтобы индекс [7] -> 5-й объект должен быть проанализирован ивставляется при разборе 5-го объекта.

Таким образом, вместо перехода от индекса [3] к индексу [4] он переходит к индексу [7].Может кто-нибудь помочь мне понять, что происходит и как это исправить?

1 Ответ

0 голосов
/ 14 февраля 2019

Цикл for продолжился в своем потоке, в то время как обратные вызовы observeUser & observePost находятся в других потоках.Глядя на ваш код, вы, вероятно, можете просто использовать appending объект в массиве results вместо inserting.Это имеет смысл, потому что вы все равно сортируете после цикла for, так почему порядок имеет значение?

...