1

I am firing off a network request inside a for loop that is within another network request. I'm using Core Data but I am fairly certain this is not a Core Data issue, and is an async issue.

The 2 print statements inside the the Firebase request print the data properly, but without the DispatchQueue the array returns as empty (before the network request completes).

Here's a picture of the crash: Crash

Here is the code itself:

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)")
                }
            }
        }
    }
}

Any help would go a long way

1 Answer 1

1

Since

let group = DispatchGroup()

is a local variable and you use observe here

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

it will re-call it after function deallocation either make it an instance variable or make this single observe

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

Also make enter inside the for loop

for friend in dictionary {  
  group.enter()
Sign up to request clarification or add additional context in comments.

1 Comment

It would have taken a long time to notice observe was causing the issue. Thank you so much

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.