Reputation: 119
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:
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
Upvotes: 1
Views: 90
Reputation: 100549
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()
Upvotes: 1