Асинхронный вызов очереди отправки - PullRequest
1 голос
/ 12 июля 2019

Я запускаю сетевой запрос внутри цикла for, который находится внутри другого сетевого запроса. Я использую Core Data, но я уверен, что это не проблема Core Data, а проблема асинхронная.

2 оператора печати внутри запроса Firebase распечатывают данные правильно, но без DispatchQueue массив возвращается как пустой (до завершения сетевого запроса).

Вот картина крушения: Crash

Вот сам код:

var userReps = [UserRepresentation]()

// Fetch all Friends -> update Core Data accordingly
func fetchFriendsFromServer(completion: @escaping (Error?) -> Void = { _ in}){
    let backgroundContext = CoreDataStack.shared.container.newBackgroundContext()

    // 1. Fetch all friends from Firebase
    FirebaseDatabase.UserDatabaseReference.child(CoreUserController.shared.userPhoneNumber).child(UserKeys.UserFriends).child(UserKeys.UserAcceptedFriends).observe(.value) { (data) in
        if let dictionary = data.value as? [String: String] {
            var userReps = [UserRepresentation]()
            let group = DispatchGroup()

            group.enter()
            for friend in dictionary {
                let friendName = friend.value
                let friendId = friend.key

                FirebaseDatabase.UserDatabaseReference.child(friendId).observe(.value, with: { (data) in
                    if let dictionary = data.value as? [String: Any] {
                        guard let gender = dictionary[UserKeys.UserGender] as? String else {return}
                        guard let bio = dictionary[UserKeys.UserBio] as? String else {return}
                        guard let status = dictionary[UserKeys.UserStatus] as? String else {return}
                        guard let avatarUrl = dictionary[UserKeys.UserAvatarUrlKey] as? String else {return}

                        let friendRepresentation = UserRepresentation(avatarUrl: avatarUrl, name: friendName, number: friendId, gender: gender, status: status, bio: bio)
                        userReps.append(friendRepresentation)
                        print("HERE, friends fetched: ", friendRepresentation)
                        print("HERE, reps fetched: ", userReps)
                        group.leave()
                    }
                })
            }

            group.notify(queue: .main) {
                // 2. Update Core Data value with Firebase values
                self.updateFriends(with: userReps, in: backgroundContext)

                // 3. Save Core Data background context
                do {
                    try  CoreDataStack.shared.save(context: backgroundContext)
                } catch let error {
                    print("HERE. Error saving changes to core data: \(error.localizedDescription)")
                }
            }
        }
    }
}

Любая помощь будет иметь большое значение

1 Ответ

1 голос
/ 12 июля 2019

Так как

let group = DispatchGroup()

- локальная переменная, и вы используете здесь наблюдение

FirebaseDatabase.UserDatabaseReference.child(friendId).observe(.value, with: { (data) in

, она вызовет ее повторно после освобождения функции, либо сделает ее переменной экземпляра, либо сделает этот единственныйсоблюдать

 FirebaseDatabase.UserDatabaseReference.child(friendId).observeSingleEvent(of:.value) { (data) in

Также сделать ввод внутри цикла for

for friend in dictionary {  
  group.enter()
...