I'm downloading some JSON from an API, but there is another prerequisite (an animation) that must be complete before we move to the next screen.
I've decided to use DispatchGroup
to do this, but also need to have a reload as well.
I've come up with a solution that uses a completion handler that is either dispatchGroup.leave
or simply moving to the next screen, since we only need to download the data once.
let dispatchGroup = DispatchGroup()
var userName: String?
func fetchData() {
dispatchGroup.enter()
dispatchGroup.enter()
resolveDataRequirements(dispatchGroup.leave)
dispatchGroup.notify(queue: .main) { [weak self] in
self?.moveToNextScreen()
}
}
func resolveDataRequirements(_ completion: @escaping(() -> Void)) {
api.resolve { [weak self] result in
switch result {
case .success(let user):
self?.userName = user
completion()
case .failure:
break
}
}
}
func moveToNextScreen() {
// move to next screen, but passes the user
}
// reload data, and once the data is downloaded move to next screen
func reloadData() {
resolveDataRequirements(moveToNextScreen)
}
// the user might choose to fetch data
fetchData()
// now if the user wanted to reload
reloadData()
Now the problem is that this is in a view model - so the user String is effectively a state that I wish to eradicate.
Is there any way I can pass the user String to dispatchGroup.notify
or similar?
You can use inout properties and change userName scope like this:
I just don't understand why you are calling enter() twice and leave() just once