BFTask
一直对我好,但我有一个抱怨:我还没有看到你应该如何cancel
任务的一个工作的例子。关于这个主题的整个文档可以在their GitHub page上找到,其中包含一个低级部分,其中包括我关心的部分:如何取消任务。
// Somewhere else.
MYCancellationToken *cancellationToken = [[MYCancellationToken alloc] init];
[obj doSomethingComplicatedAsync:cancellationToken];
// When you get bored...
[cancellationToken cancel];
他们的代码片段后跟:
注意:取消令牌实现应该是线程安全的。
我想知道以下内容:
cancel
界面上提供BFTask
方法?他们有一个属性,表示任务是否被取消,但没有办法取消它。cancellationToken(s)
本身包含BFTask
财产?cancel
的实施是否与任务本身强烈耦合?或者是一般的实现,如cancelAllOperations
的NSOperationQueue
?BFTask
是Future and Promises构造的实现:
“未来是变量的只读占位符视图,而承诺是一个可写的单一赋值容器,用于设置未来的值”。
基本上,BFTask
是Future
:它是变量的只读占位符视图。
BFTaskCompletionSource
是一个承诺:它是一个可写的单一分配容器,它设定了未来的价值。 (或错误 - 或取消任务)
BFTask
公共接口仍然是只读的,因此它不允许您直接取消它。BFCancellationToken
令牌只存储一个状态,BFTask
可以检查。你的异步任务代码基本上可以定期检查cancellationRequested
是否设置为true,这允许你手动取消你的任务。
注意:Bolts框架iOS docs说:“任务有点像JavaScript承诺”,这可能令人困惑,因为它确实是一个未来。我认为它的Javascript起源只是错误的。在Bolts中有一个非常有用的取消令牌实现,但由于某些原因,它不会在头文件之外的任何文档中记录。关键是使用BFCancellationTokenSource
。您需要保留对BFCancellationTokenSource
的引用才能发布和取消BFCancellationToken
。
在我的例子中,我有一个名为cancellableFunction()
的特殊函数,它连续发出一堆任务。如果在最后一次调用完成之前再次调用该函数,我希望取消上一次调用的未完成任务。
这里的关键是将token
传递给每个continueWith
函数调用。如果token
在任何时候通过tokenSource
取消,未得到的successBlock
s将不会被执行。您还可以通过每个task.cancelled
中的BFContinuationBlock
检查取消状态(显然在成功块中为假)。
这是一个例子:
class ViewController: UIViewController {
...
// instance reference to tokenSource so that it can be cancelled by any function in the ViewController
var tokenSource: BFCancellationTokenSource?
...
func cancellableFunction() -> BFTask {
// First cancel the previous token
tokenSource?.cancel()
// Replace the previous TokenSource with a new one
tokenSource = BFCancellationTokenSource()
// Issue new Token from the new TokenSource
let token = tokenSource!.token
return functionThatReturnsBFTask().continueWithSuccessBlock({ (task:BFTask) -> AnyObject? in
...
return nil
}, cancellationToken: token).continueWithExecutor(BFExecutor.mainThreadExecutor(), successBlock: { (task:BFTask) -> AnyObject? in
...
return nil
}, cancellationToken: token).continueWithBlock({ (task:BFTask) -> AnyObject? in
// Here you can perform an actions you want to take on cancellation
if task.cancelled {
}
...
return nil
}, cancellationToken: token)
}
...
}
使用[self.bfTaskCancelationToken cancel];
代码取消系列BFTask
注册BFCancellationTokenSource
self.bfTaskCancelationToken = [BFCancellationTokenSource cancellationTokenSource];
[self.bfTaskCancelationToken.token registerCancellationObserverWithBlock:^{
NSLog(@"task hasbeen Cancelled.....");
//Do stuff on cancelation task
} ];
实施BFTask系列
注意:在cancellationToken:self.bfTaskCancelationToken.token
之后有[task continueWithBlock:^id(BFTask *task)
代码
[[[self showAlertProgressHud] continueWithBlock:^id(BFTask *taskLog) {
BFTask *task = [BFTask taskWithResult:nil];
for (int i=0; i<self.arrAssetPhotos.count; i++) {
AIAssetPhoto *assetPhoto = self.arrAssetPhotos[i];
task = [task continueWithBlock:^id(BFTask *task) {
// Return a task that will be marked as completed.
return [self processOnAssetPhoto:assetPhoto index:i completion:NULL];
} cancellationToken:self.bfTaskCancelationToken.token];
}
return task;
}] continueWithBlock:^id(BFTask *task) {
// all asset photos process are done.
return nil;
}];
如何取消连续的BFtask?
//just by calling one simple method
[self.bfTaskCancelationToken cancel];