所以我有一个分页 API,每次用户进入屏幕时我都必须调用它。下面的代码工作正常,但如果说 API 调用正在进行并且用户退出并再次返回,那么就会出现一个问题,而不是两个执行同时开始。 并且必须等待两个执行完成。 所以,我想要的是停止正在进行的 API 调用,并在请求新的 API 时启动新的 API 调用 如果此设置有任何错误,请通知我我做错了什么?
func storeAllData(matchID: Int64) {
GlobalVariable.isFetchingData = true
dbManager = DbManager.shared
if let lastScore = dbManager.getLastBallForCurrentMatch(matchID: matchID) {
self.fetchAllScore(scoreID: lastScore.id ?? 0, matchID: matchID)
} else {
self.fetchAllScore(scoreID: 0, matchID: matchID)
}
}
func fetchAllScore(scoreID: Int = 0, matchID: Int64) {
let id = matchID
backgroundQueue.async { [self] in
autoreleasepool {
fetchPaginatedData(matchID:Int(id), scoreID: scoreID, page: 1)
dispatchGroup.wait()
print("All API calls finished")
}
}
}
func fetchPaginatedData(matchID: Int,scoreID: Int = 0, page: Int) {
dispatchGroup.enter()
MatchesNetworkManager.sharedInstance.getAllScore(matchID: Int64(matchID), scoreID: Int64(scoreID), page: Int64(page), completionHandler: { [weak self] (allSocre, isSuccess, errorStr) in
if isSuccess {
if allSocre?.match?.scores != nil {
self?.oldScores.append(contentsOf: ((allSocre?.match?.scores)!))
self?.backgroundQueue.async {
if let scores = allSocre?.match?.scores as? [Scores] {
self?.dbManager.insertRecords(matchID: matchID, records: scores)
DispatchQueue.main.async {
self?.oldScores = []
if allSocre?.page_num ?? 0 == 1 {
self?.updateScoreView()
}
if (allSocre?.page_num ?? 0) < (allSocre?.total_pages ?? 0) {
self?.fetchPaginatedData(matchID: matchID,page: (allSocre?.page_num ?? 1) + 1)
} else {
// All pages have been fetched
GlobalVariable.isFetchingData = false
print("All API calls finished")
NotificationCenter.default.post(name: .refreshMarketView, object: nil, userInfo: nil)
self?.dispatchGroup.leave()
}
}
}
}
} else {
self?.updateScoreView()
GlobalVariable.isFetchingData = false
}
} else {
print("API call error: \(errorStr)")
self?.updateScoreView()
GlobalVariable.isFetchingData = false
self?.dispatchGroup.leave()
}
})
}
这些(和类似)平台上大多数并发抽象的现实是,一旦启动,工作单元几乎完全无法被强制取消(除了终止进程)。
通常处理此问题的方法是检查工作单元本身的“内部”标志,表明它们应该被取消,此时它们可以执行任何需要的清理工作(如果有),并提前返回。如果您有一个调度组,则可以将一个标志与该组关联起来,然后在每个操作开始时(或在该操作内循环的每次迭代的顶部)显式检查该标志,如果该组则提前返回已取消。 您可以临时执行此操作。您可以使用现有的抽象(如
NSOperation
的
cancel
方法),但即使在那里,您也会注意到Discussion 部分的第一行说:“此方法不会强制您的操作代码停止。”您的操作代码仍必须检查该标志。 例如,您可以使用
NSBlockOperation
,创建操作实例,然后捕获对执行实际工作的块的闭包内的
NSBlockOperation
实例的归零弱引用,然后使用该引用来检查是否NSBlockOperation
已被取消(或解除分配)。长话短说,天下没有免费的午餐。