从NSOperation中取消NSOperationQueue

时间:2010-07-04 09:46:12

标签: iphone objective-c cocoa cocoa-touch nsoperationqueue

我有一些iPhone SDK 4.0代码初始化NSOperationQueue,然后添加三个类(ClassAClassBClassC)来一个接一个地运行。 ClassAClassBClassC都是NSOperation的子类。

相关代码包含在下面。

ClassA *classA = [[ClassA alloc] init];
ClassB *classB = [[ClassB alloc] init];
ClassC *classC = [[ClassC alloc] init];

[classB addDependency:classA];
[classC addDependency:classB];

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[queue addOperation:classA];
[queue addOperation:classB];
[queue addOperation:classC];

[classA release];
[classB release];
[classC release];
[queue release];

依赖的原因是因为classB只应在classA成功完成其操作时运行。同样,classC只应在classB成功完成时运行。

目前,如果classB未成功完成,我很难确定如何防止classA运行。继续这个例子,我想在某种程度上从[NSOperationQueue cancelAllOperations]内引出classA,但我不知道如何从NSOperationQueue内处理父classA(这是一个NSOperation子类。这只是我最初的想法,所以我愿意接受任何其他更好的建议来实现相同的结果!

每个类中都有条件代码来确定它们是否已正确完成 - 目前它们只是NSLogging“成功”或“失败”到控制台进行调试。在一个完美的世界中,我希望能够用一些代码替换每个类中的NSLog(@"Fail")语句,这些代码将阻止NSOperationQueue中的所有其他类运行。

任何建议都会受到欢迎(并赞赏)。

3 个答案:

答案 0 :(得分:3)

您可以在classA中设置属性:

@property (readonly) BOOL completedSucessfully;

并在classA的主要方法结束时将其设置为YES。

然后,只需在classB的开头检查它。

- (void)main {
    if (NO == [[dependencies objectAtIndex:0] completedSucessfully])
        return;

现在,如果classA报告失败,classB将停止。

注意:在上面的示例中,您可能需要更多错误检查,即确保您具有依赖关系,检查它是否是正确的类等。

- (void)main {
    for (id *temp in [self dependencies])
        if ([temp isKindOfClass:[ClassA class]])
            if (NO == [(ClassA *)temp finishedSucessfully])
                return;

答案 1 :(得分:1)

我建议,如果速度不是问题,你可以同步工作。否则你可以使用:

[selector:@selctor(StartB) waitUntilTaskComplete:YES];

答案 2 :(得分:1)

在观看了有关高级NSOperation技术的WWDC 2015会议之后(强烈推荐),我开始在我自己的代码中深入使用它们。以下是实现此目的的一些建议

  1. 在NSOperation中,您可以调用[self currentQueue]来获取"启动操作的操作队列,如果无法确定队列,则调用nil。"然后,您可以在返回的队列上调用cancelAllOperations。根据经验,我很难使用这种方法,因为如果你在主队列上显式运行代码,在闭包/块中有代码,或者调用第三方库,那么返回的队列可能根本就不是初始队列。在这种情况下,调用cancelAllOperations将不会导致预期的行为 - 而是取消不同队列上的操作。

  2. 子类NSOperation包含初始NSOperationQueue和子类NSOperationQueue的属性,以便在将操作添加到队列时设置属性。然后在self.initialQueue上调用cancelAllOperations。这是我使用的方法,适用于上述所有场景。

  3. 您可以调用操作"取消"而不是取消队列级别的所有操作。方法并完成您的操作。如果您的操作已经编写为符合Apple的操作指南,那么它们在启动时都会检查isCancelled,如果为true则中止处理。这是一个微妙的区别:当您取消队列操作时,任何尚未启动的操作都将无法启动。当您将操作设置为isCancelled时,后续操作将启动,但(应该)之后很快完成。这允许后续操作可能执行某些清理,错误处理或用户通知的情况。