Ios 从NSO操作返回数据?

Ios 从NSO操作返回数据?,ios,objective-c,nsoperation,Ios,Objective C,Nsoperation,我正在创建大量的NSOperations(子类),它们对一组数据进行排序。完成后,我希望他们“返回”数据,并将其放入可变数组或其他东西中。秩序不重要 这样的事情可能吗?当然可以。在NSOperation子类中声明委托。然后在手术结束后 if([self.delegate respondsToSelector:@selector(YourDelegate:)]) { [(NSObject *)self.delegate performSelectorOnMainThread:@select

我正在创建大量的
NSOperation
s(子类),它们对一组数据进行排序。完成后,我希望他们“返回”数据,并将其放入可变数组或其他东西中。秩序不重要


这样的事情可能吗?

当然可以。在NSOperation子类中声明委托。然后在手术结束后

if([self.delegate respondsToSelector:@selector(YourDelegate:)]) {
    [(NSObject *)self.delegate performSelectorOnMainThread:@selector(YourDelegate:) withObject:self waitUntilDone:NO];
}
在用户界面中


协议委托模式的替代方案是完成块。例如,在一些基于随机
NSURLConnection
的操作中,我定义了一个完成块
typedef
(稍后只是为了简化块语法),如果成功,它将返回一个
NSData
,否则返回一个
NSError

typedef void(^CustomOperationCompletionBlock)(NSData *data, NSError *error);
然后,我可以为我的
NSOperation
子类定义块属性,例如:

@property (nonatomic, copy) CustomOperationCompletionBlock successFailureBlock;
我经常会有一个我操作的
init
方法的格式副本,它允许我在
init
过程中设置完成块(除了我想要初始化的任何其他内容):

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

- (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
子类返回数据。

+1显然,您应该在
@selector
中引用相同的方法名称,并在委托中引用相同的方法。例如,如果委托中的方法是
yourOperationDidFinish:
,那么您应该引用
@selector(yourOperationDidFinish:)
。更好的是,您可能应该为委托定义一个定义,以消除此处的任何歧义。同样,在这个答案中,声明
委托
属性
也是谨慎的。
- (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];