Okay, after some comments for more information to this question, let's try it:
In a viewController I'm calling a function loadPosts(). In this function I'm calling api.shared.function observePosts(). observePosts() downloads all posts at a specified database reference. with the first downloaded post back in the loadPosts() I'm calling self.fetchUser(uid: post.uid) in VC. This call api.shared.function observeUser() which gives me the user from the current post downloaded.
In observeUser() I'm filling users-array with user-object from type UserModel and in completion-block of loadPosts() I'm filling posts-array with post-object from type PostModel. After insert the post to posts-array at:0 I reload the tableView and get a view of all downloaded posts with matching info about the user that created it. (code comes after description)
Means: If there are 5 posts from type PostModel - there must be 5 userModel's, too. Every function is called 5 times - in this example with 5. Every function is running 5 times. (Tested with a print("call loadPosts")).
What I finally want is: Get the posts and the users - fill the arrays (when all posts at this time) are loaded. Make this step again - with posts2 and users2. If all four arrays are filled - an algorithm get them together in one posts-array and one users-array, like: post[0], post1, post[2], post2[0], post[3], post[4], post[5], post21 ... Of course the users will be putting together in one as well. THIS PART IS NO PROBLEM! I HAVE A WORKING CODE ... with hardcoded strings in the arrays
My problem is: When I'm calling a function at the end of a function it can be fact that the asynchronous task of loading the posts ( users ) is not done. So, how can I make the code "wait to complete"? I have tried this from StackOverflow and also tried to work with DispatchQueue but that don't work, too.
Before the code is coming - here is my workaround: xCode 11.3.1 with Swift 5. ( async / await - solutions from the comments are not possible )
Code(s): In ViewController:
viewDidLoad => loadPosts()
loadPosts(){
Api.shared.observePosts { (post) in
self.fetchUser(uid: UserUid, completed:{
self.posts.insert(post, at:0)
self.tableView.reloadData()
})
}
}
func fetchUser(uid: String, completed: @escaping () -> Void) {
Api.shared.observeUser(uid: uid) { (user) in
self.users.insert(user, at: 0)
completed()
}
}
In Api
// load posts
func observePosts(completion: @escaping (PostModel) -> Void){
REF_POSTS.observe(.childAdded) { (snapshot) in
guard let dic = snapshot.value as? [String: Any] else { return }
let newPost = PostModel(dictionary: dic, key: snapshot.key)
completion(newPost)
}
}
// load users
func observeUser(uid: String, completion: @escaping(UserModel) -> Void){
REF_USERS.child(uid).observeSingleEvent(of: .value) { (snapshot) in
guard let dic = snapshot.value as? [String: Any] else { return }
let newUser = UserModel(dictionary: dic)
completion(newUser)
}
}
I hope that now is clear what I'm doing and what I want to to after modifying the code. Any help or info is welcome.