【问题标题】:Perform selector on parent NSOperation在父 NSOperation 上执行选择器
【发布时间】:2010-05-11 23:11:12
【问题描述】:

我扩展了 NSOperation(称为 A),其中包含其他 NSOperation 的 NSOperationQueue(这是与 A 不同的另一个扩展类,将这些操作称为 B)。当操作 A 正在运行(执行 B 操作)时,当 B 操作上发生某些事件时,我如何在操作 A 上调用特定函数/方法?例如,完成它的每个操作 B 都会在操作 A 返回自身时调用一个函数?

*嵌套的 NSOperation 和 NSOperationQueue(s)

希望这个mockup伪代码可以帮助绘制图片。

//My classes extended from NSOperation

NSOperation ClassA

NSOperation ClassB

//MainApp

-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    ClassA A1;

    ClassA A2;

    NSOperationQueue Queue;
    Queue AddOperation: A1;
    Queue AddOperation: A2;


}

//Main of ClassA

-(void)main {

     ClassB B1;

     ClassB B2;

     NSOperationQueue Queue;
     Queue AddOperation: B1;
     Queue AddOperation: B2;

}

//Main of ClassB

-(void)main {

   //Do some work and when done call selector on ClassA above

}

【问题讨论】:

  • 听起来既复杂又可怕。你想做什么?
  • 一些伪代码可能会使问题更清楚。
  • @Dave DeLong:这是一个编码实验。该应用程序需要一些指向服务器上下载文件的 URL。为每个 URL 创建 NSOperation,确定文件的大小并将其分成块。从那里,文件的每个块都由单独的 NSOperation 下载。这有意义吗。
  • 我称之为嵌套的NSOperations,我也有同样的问题。

标签: objective-c cocoa nsoperation


【解决方案1】:

NSOperation 具有注册依赖项的机制。请参阅NSOperation's documentationaddDependency:

让我们拆分A 所做的工作:AX:生成Bs,和AY:收集B 中的数据。 我认为最好设计B,这样它就可以在没有A 的情况下使用。让B 只需下载数据并将其保存在属性data 中,如

@interface B:NSOperation{
}
-initWithURL:(NSURL*)url atPosition:(NSUInteger)position;
@property (readonly)NSData* data;
@end;

A 不必有自己的队列,每个对象一个。生成B 也不需要太多时间, 所以AX 不一定是一个操作。

所以,我只需定义操作AYB,只准备一个队列,然后执行类似的操作

NSOperationQueue* queue=...;
NSArray* urls = ... ;
for(NSURL* url in urls){
     AY* ay=[[AY alloc] init];
     for(chunks in url){
         B* b= an instance for B for the chunk in url
         [ay addDependency:b];
         [queue addOperation:b];
     } 
     [queue addOperation:ay];
}

然后,在AY的主目录中,你可以

-main{
      NSArray*bs=[self dependencies];
      for(B*b in bs){
           NSData* data=b.data;
      }
}

请注意,由于依赖关系,可以保证在运行AY 时,所有B 都已完成其操作。 这样B的实现就独立于A了。

【讨论】:

  • 不要认为这正是我想要的。由于对象 A(它是 NSOperation 的扩展)产生了许多其他对象 B(它们也是 NSOperation 的扩展)并且对象 B 下载了一大块文件,我希望每个对象 B 联系他们的父对象 A 并告诉他们“嘿,我下载了文件的这么多字节”(或任何其他消息)。
  • 我建议将对象 A 的任务拆分为 AX:生成 B 和 AY:从 B 收集数据。我会相应地编辑我的答案。
【解决方案2】:

我编写了一个名为 MXSuperOperation 的类来为我目前正在开发的应用程序嵌套 NSOperations。我已经在这里发布了:

https://gist.github.com/joerick/e4d2c99a2127715d9bc3

子类 MXSuperOperation 并在 -mainError: 方法中添加子操作。

@interface OperationA : MXSuperOperation

@end

@implementation OperationA

- (BOOL)mainError:(NSError **)error
{
    [self addSuboperation:[OperationB new]];
    [self addSuboperation:[OperationB new]];

    return YES;
}

@end

然后要在所有OperationBs 的末尾运行一些东西,您可以添加一个completionBlock 到 operationA:

[operationA setCompletionBlockWithSuccess:^(id operation) {
    NSLog(@"success");
} failure:^(id operation, NSError *error) {
    NSLog(@"error %@", error);
}];

或者您可以在 OperationA 中实现-endError:(取决于您希望如何构造代码)。

请注意,这个类是基于我创建的一个名为 MXCheckedOperation 的 NSOperation 子类构建的,它只是编码了 NSOperations 的成功/失败和错误报告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多