gpt4 book ai didi

iphone - 将 NSOperation 子类化为并发和可取消

转载 作者:行者123 更新时间:2023-12-03 18:11:16 28 4
gpt4 key购买 nike

我找不到关于如何子类化 NSOperation 的好的文档并发并支持取消。我阅读了 Apple 文档,但找不到“官方”示例。

这是我的源代码:

@synthesize isExecuting = _isExecuting;
@synthesize isFinished = _isFinished;
@synthesize isCancelled = _isCancelled;

- (BOOL)isConcurrent
{
return YES;
}

- (void)start
{
/* WHY SHOULD I PUT THIS ?
if (![NSThread isMainThread])
{
[self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
return;
}
*/

[self willChangeValueForKey:@"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:@"isExecuting"];


if (_isCancelled == YES)
{
NSLog(@"** OPERATION CANCELED **");
}
else
{
NSLog(@"Operation started.");
sleep(1);
[self finish];
}
}

- (void)finish
{
NSLog(@"operationfinished.");

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

_isExecuting = NO;
_isFinished = YES;

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

if (_isCancelled == YES)
{
NSLog(@"** OPERATION CANCELED **");
}
}

在我发现的例子中,我不明白为什么使用 performSelectorOnMainThread: 。它会阻止我的操作同时运行。

此外,当我注释掉该行时,我的操作会同时运行。然而, isCancelled标志没有被修改,即使我已经调用 cancelAllOperations .

最佳答案

好的,据我所知,您有两个问题:

  • 您需要performSelectorOnMainThread:吗?出现在代码注释中的段?这段代码有什么作用?
  • 为什么是_isCancelled调用 cancelAllOperations 时不会修改标志在 NSOperationQueue包含这个操作?

  • 让我们按顺序处理这些。我将假设您的子类 NSOperation被称为 MyOperation ,只是为了方便解释。我会解释你的误解,然后给出一个更正的例子。

    1. 同时运行 NSOperations

    大多数情况下,您会使用 NSOperation s 带有 NSOperationQueue ,从你的代码来看,这听起来像是你在做什么。在这种情况下,您的 MyOperation无论 -(BOOL)isConcurrent 是什么,都将始终在后台线程上运行方法返回,因为 NSOperationQueue s 明确设计为在后台运行操作。

    因此,您通常不需要覆盖 -[NSOperation start]方法,因为默认情况下它只是调用 -main方法。那是您应该覆盖的方法。默认 -start方法已经处理设置 isExecutingisFinished在适当的时候为您服务。

    所以如果你想要一个 NSOperation要在后台运行,只需覆盖 -main方法并将其放在 NSOperationQueue 上.
    performSelectorOnMainThread:在您的代码中会导致 MyOperation 的每个实例始终在主线程上执行其任务。由于一次只能在一个线程上运行一段代码,这意味着没有其他的 MyOperation s 可能正在运行。 NSOperation的整个目的和 NSOperationQueue是在后台做一些事情。

    唯一要强制执行主线程的时间是在更新用户界面时。如果您在 MyOperation 时需要更新 UI完成,这就是你应该使用 performSelectorOnMainThread: 的时候.我将在下面的示例中展示如何做到这一点。

    2. 取消一个 NSOperation
    -[NSOperationQueue cancelAllOperations]调用 -[NSOperation cancel]方法,这会导致后续调用 -[NSOperation isCancelled]返回 YES . 然而 ,你做了两件事来使这无效。
  • 您正在使用 @synthesize isCancelled覆盖 NSOperation 的 -isCancelled方法。没有理由这样做。 NSOperation已经实现 -isCancelled以完全可以接受的方式。
  • 您正在检查自己的 _isCancelled用于确定操作是否已被取消的实例变量。 NSOperation保证[self isCancelled]将返回 YES如果操作已被取消。确实如此 不是 保证您的自定义 setter 方法将被调用,也不保证您自己的实例变量是最新的。你应该检查 [self isCancelled]

  • 你应该做什么

    标题:
    // MyOperation.h
    @interface MyOperation : NSOperation {
    }
    @end

    和实现:
    // MyOperation.m
    @implementation MyOperation

    - (void)main {
    if ([self isCancelled]) {
    NSLog(@"** operation cancelled **");
    }

    // Do some work here
    NSLog(@"Working... working....")

    if ([self isCancelled]) {
    NSLog(@"** operation cancelled **");
    }
    // Do any clean-up work here...

    // If you need to update some UI when the operation is complete, do this:
    [self performSelectorOnMainThread:@selector(updateButton) withObject:nil waitUntilDone:NO];

    NSLog(@"Operation finished");
    }

    - (void)updateButton {
    // Update the button here
    }
    @end

    请注意,您不需要对 isExecuting 执行任何操作, isCancelled , 或 isFinished .这些都是自动为您处理的。只需覆盖 -main方法。就这么简单。

    (注意:从技术上讲,这不是“并发” NSOperation ,因为 -[MyOperation isConcurrent] 将返回 NO 如上所述。但是,它将在后台线程上运行。真正的 isConcurrent 方法应该命名为 -willCreateOwnThread ,因为这是对方法意图的更准确描述。)

    关于iphone - 将 NSOperation 子类化为并发和可取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3859631/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com