首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何取消NSBlockOperation

如何取消NSBlockOperation
EN

Stack Overflow用户
提问于 2011-11-14 01:20:16
回答 4查看 20.1K关注 0票数 50

我有一个很长的运行循环,我想用NSOperation在后台运行。我想使用一个块:

代码语言:javascript
复制
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
   while(/* not canceled*/){
      //do something...
   }
}];

问题是,我如何检查它是否被取消。该块不接受任何参数,并且operation在被该块捕获时为空。有没有办法取消块操作?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-11-14 01:25:07

多伊尔。亲爱的未来谷歌人:当按块复制时,operation当然是零,但它不一定要复制。它可以使用__block进行限定,如下所示:

代码语言:javascript
复制
//THIS MIGHT LEAK! See the update below.
__block NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
   while( ! [operation isCancelled]){
      //do something...
   }
}];

更新:

在进一步的冥想中,我想到这将在ARC下创造一个保留周期。在ARC中,我相信__block存储是被保留的。如果是这样的话,我们就有麻烦了,因为NSBlockOperation还保留了对传入块的强引用,该块现在具有对操作的强引用,该操作具有对传入块的强引用,其中…

它有点不那么优雅,但使用显式弱引用应该会打破这个循环:

代码语言:javascript
复制
NSBlockOperation *operation = [[NSBlockOperation alloc] init];
__weak NSBlockOperation *weakOperation = operation;
[operation addExecutionBlock:^{
   while( ! [weakOperation isCancelled]){
      //do something...
   }
}];

任何对更优雅的解决方案有想法的人,请评论!

票数 72
EN

Stack Overflow用户

发布于 2012-10-23 20:41:33

以强化jemmons的答案。WWDC 2012 session 211 - Building Concurent User Interfaces (33分钟内)

代码语言:javascript
复制
NSOperationQueue* myQueue = [[NSOperationQueue alloc] init];
NSBlockOperation* myOp = [[NSBlockOperation alloc] init];

// Make a weak reference to avoid a retain cycle
__weak NSBlockOperation* myWeakOp = myOp;

[myOp addExecutionBlock:^{
    for (int i = 0; i < 10000; i++) {
        if ([myWeakOp isCancelled]) break;
        precessData(i);
    }
}];
[myQueue addOperation:myOp];
票数 46
EN

Stack Overflow用户

发布于 2017-06-20 07:45:21

使用Swift 5,您可以使用addExecutionBlock(_:)创建一个可取消的BlockOperationaddExecutionBlock(_:)有以下声明:

代码语言:javascript
复制
func addExecutionBlock(_ block: @escaping () -> Void)

将指定的块添加到接收器的要执行的块列表中。

下面的示例显示了如何实现addExecutionBlock(_:)

代码语言:javascript
复制
let blockOperation = BlockOperation()

blockOperation.addExecutionBlock({ [unowned blockOperation] in
    for i in 0 ..< 10000 {
        if blockOperation.isCancelled {
            print("Cancelled")
            return // or break
        }
        print(i)
    }
})

请注意,为了防止BlockOperation实例与其执行块之间的保留循环,您必须在执行块内使用带有对blockOperationweakunowned引用的捕获列表。

下面的游乐场代码显示了如何取消BlockOperation子类实例,并检查它与其执行块之间是否存在保留周期:

代码语言:javascript
复制
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

class TestBlockOperation: BlockOperation {
    deinit {
        print("No retain cycle")
    }
}

do {
    let queue = OperationQueue()

    let blockOperation = TestBlockOperation()
    blockOperation.addExecutionBlock({ [unowned blockOperation] in
        for i in 0 ..< 10000 {
            if blockOperation.isCancelled {
                print("Cancelled")
                return // or break
            }
            print(i)
        }
    })

    queue.addOperation(blockOperation)

    Thread.sleep(forTimeInterval: 0.5)
    blockOperation.cancel()
}

这将打印:

代码语言:javascript
复制
0
1
2
3
...
Cancelled
No retain cycle
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8113268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档