我正在使用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语句检查)但它并没有真正结束操作。我仍然不是很自信我做对了
有人可以告诉我哪里出错了吗?
非常感谢
答案 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];
}