iPhone - 从NSOperation返回

时间:2009-11-20 13:48:28

标签: iphone multithreading nsoperation

我正在使用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]; [operationQueue 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,但即使这样也不会改变任何东西。

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

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

非常感谢

2 个答案:

答案 0 :(得分:2)

来自NSOperation Class Reference

  

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

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

  

- (void)cancel

     

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

答案 1 :(得分:0)

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

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

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

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

- (IBAction) clickButton: (UIBarButtonItem *) item{
 [myOperation cancel]; 
}