0

我正在使用 NSOperation 的子类来执行一些后台进程。我希望在用户单击按钮时取消操作。

这是我的 NSOperation 子类的样子

- (id)init{
    self = [super init];
    if(self){
        //initialization code goes here
        _isFinished = NO;
        _isExecuting = NO;
    }

    return self;
}

- (void)start
{
    if (![NSThread isMainThread])
    {
        [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
        return;
    }
    [self willChangeValueForKey:@"isExecuting"];
    _isExecuting = YES;
    [self didChangeValueForKey:@"isExecuting"];

    //operation goes here
}

- (void)finish{
    //releasing objects here

    [self willChangeValueForKey:@"isExecuting"];
    [self willChangeValueForKey:@"isFinished"];

    _isExecuting = NO;
    _isFinished = YES;

    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
}

- (void)cancel{
    [self willChangeValueForKey:@"isCancelled"];

    [self didChangeValueForKey:@"isCancelled"];
    [self finish];
}

这就是我将此类的对象添加到队列并侦听 KVO 通知的方式

operationQueue = [[NSOperationQueue alloc] init]; [操作队列 setMaxConcurrentOperationCount:5]; [operationQueue addObserver:self forKeyPath:@"operations" options:0 context:&OperationsChangedContext];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == &OperationsChangedContext) {
        NSLog(@"Queue size: %u", [[operationQueue operations] count]);
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

要取消操作(例如单击按钮),我尝试调用 -cancel 但它没有任何区别。还尝试调用 -finish 但即使这样也不会改变任何东西。

每次我向队列添加操作时,队列大小只会增加。调用完成(使用 NSLog 语句检查),但它并没有真正结束操作。我仍然不太有信心我做对了

有人可以告诉我哪里出错了吗?

非常感谢

4

2 回答 2

2

NSOperation 类参考

取消操作不会立即强制它停止正在执行的操作。尽管所有操作都需要遵守 isCancelled 返回的值,但您的代码必须显式检查此方法返回的值并根据需要中止

即,cancel除非您的实现强制执行此操作,否则该方法实际上不会取消操作。同样,从相关部分

- (void)cancel

此方法不会强制您的操作代码停止。相反,它会更新对象的内部标志以反映状态的变化。

于 2009-11-20T15:39:15.083 回答
0

您只需要以下内容即可实现:

在您的 NSOperation 子类中,添加到 main 方法

 while (! self.isCancelled) {
  [NSThread sleepForTimeInterval:1];
 }

在 GUI 类中,您需要 NSOperation 子类的实例变量,在管理按钮的方法中,您取消 NSOperation 子类。例如:

- (IBAction) clickButton: (UIBarButtonItem *) item{
 [myOperation cancel]; 
}
于 2010-06-17T00:18:37.133 回答