6

我正在创建许多对NSOperation一堆数据进行排序的 s (子类)。完成后,我希望他们“返回”该数据并将其放入可变数组或其他东西中。顺序无所谓。

这样的事情可能吗?

4

2 回答 2

16

协议委托模式的替代方案是完成块。例如,在一些基于随机NSURLConnection的操作中,我定义了一个完成块typedef(只是为了简化后面的块语法),它返回一个NSDataif 成功或NSErrorif not:

typedef void(^CustomOperationCompletionBlock)(NSData *data, NSError *error);

然后我可以为我的NSOperation子类定义一个块属性,例如:

@property (nonatomic, copy) CustomOperationCompletionBlock successFailureBlock;

我经常会复制我init的操作方法,让我在此init过程中设置完成块(除了我想要初始化的任何其他内容):

- (instancetype)initWithURL:(NSURL *)url successFailureBlock:(CustomOperationCompletionBlock)successFailureBlock;

然后,我在操作中处理错误和/或成功的各种方法将调用该完成块以将数据传回:

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    if (self.successFailureBlock) {
        // whether you call the completion block on the main queue, or use whatever queue the operation is using, is up to you. Here I'll call the completion block on the main queue:

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.successFailureBlock(nil, error);
        }];
    }

    [self completeOperation];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    if (self.successFailureBlock) {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.successFailureBlock(self.data, nil);
        }];
    }

    [self completeOperation];
}

而且,要将此操作与自定义完成块处理程序一起使用,当我启动我的操作时,我可以只传递一个自定义完成块。例如,如果成功则保存数据,否则记录错误:

CustomOperation *operation = [[CustomOperation alloc] initWithURL:url successFailureBlock:^(NSData *data, NSError *error) {
    if (error)
        NSLog(@"CustomOperation error: %@", error);
    else         
        [data writeToFile:path atomically:YES];
}];

[queue addOperation:operation];

显然,您将更改块typedef以传回对您的操作有意义的任何对象。但这说明了NSOperation子类返回数据的基于块的机制的基本模式。

于 2013-10-15T06:25:02.067 回答
4

当然。在 NSOperation 子类中声明一个委托。然后在操作完成后

if([self.delegate respondsToSelector:@selector(YourDelegate:)]) {
    [(NSObject *)self.delegate performSelectorOnMainThread:@selector(YourDelegate:) withObject:self waitUntilDone:NO];
}

在用户界面中

-(void)YourOperationDidFinish:(YourOperation *)downloader {
    if(downloader.downloadItem) {
        // processing with your object       
    }
}
于 2013-10-15T05:31:42.400 回答