iPhone - 从 NSOperation 返回

发布于 2024-08-11 09:42:46 字数 1804 浏览 2 评论 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]; [操作队列设置最大并发操作计数:5]; [操作队列addObserver:self forKeyPath:@“操作”选项:0上下文:&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 语句检查),但它并没有真正结束操作。我仍然不太有信心我做对了

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

多谢

I am using a subclass of NSOperation to do some background processes. I want the operation to be cancelled when the user clicks a button.

Here's what my NSOperation subclass looks like

- (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];
}

And this is how I am adding objects of this class to a queue and listening for KVO notifications

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];
    }
}

To cancel an operation (on a button click for instance), I tried calling -cancel but it doesn't make a difference. Also tried calling -finish but even that doesn't change anything.

Every time I add an operation to the queue, the queue size only increases. finish is called (checked using NSLog statements) but it doesn't really end the operation. I'm still not very confident I'm doing this right

Can someone please tell me where I am going wrong?

Thanks a lot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清风挽心 2024-08-18 09:42:46

来自NSOperation类参考

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

cancel 方法实际上并不取消操作,除非您的实现强制执行此操作。再次,来自相关的 部分

- (void)取消

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

From the NSOperation Class Reference:

Cancelling an operation does not immediately force it to stop what it is doing. Although respecting the value returned by the isCancelled is expected of all operations, your code must explicitly check the value returned by this method and abort as needed.

i.e. the cancel method does not actually cancel the operation unless your implementation enforces this. Again, from the relevant section:

- (void)cancel

This method does not force your operation code to stop. Instead, it updates the object’s internal flags to reflect the change in state.

不醒的梦 2024-08-18 09:42:46

您只需要执行以下操作即可实现它:

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

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

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

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

You just need the following to achieve it:

In your NSOperation subclass, add to main method

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

In the GUI class, you need an instance variable to your NSOperation subclass, and in the method that manages the button, you cancel your NSOperation subclass. For instance:

- (IBAction) clickButton: (UIBarButtonItem *) item{
 [myOperation cancel]; 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文