我正在从API下载一些JSON,但是在我们移动到下一个屏幕之前,必须完成另一个先决条件(动画)。
我决定使用DispatchGroup
来做到这一点,但也需要重新加载。
我已经想出了一个解决方案,使用一个完成处理程序,要么是dispatchGroup.leave
或简单地移动到下一个屏幕,因为我们只需要下载数据一次。
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()
现在的问题是,这是在一个视图模型中-所以用户字符串实际上是一个我希望根除的状态。
是否有任何方法可以将用户字符串传递给dispatchGroup.notify
或类似的?
您可以使用inout属性并像这样更改userName范围:
func fetchData() {
var userName = ""
dispatchGroup.enter()
dispatchGroup.enter()
resolveDataRequirements(dispatchGroup.leave, &userName)
dispatchGroup.notify(queue: .main) { [weak self] in
self?.moveToNextScreen(userName)
}
}
func resolveDataRequirements(_ completion: @escaping(() -> Void), _ userName: inout String) {
api.resolve { [weak self] result in
switch result {
case .success(let user):
userName = user
completion()
case .failure:
break
}
}
}
func moveToNextScreen(_ userName: String) {
print(userName)
}
我只是不明白为什么你调用enter()两次而只调用leave()一次