Return data from NSOperation?

浪子不回头ぞ 提交于 2019-12-18 16:54:37

问题


I'm creating a lot of NSOperations (subclasses) that sort through a bunch of data. When they're done, I'd like them "return" that data and put it into a mutable array or something. Order doesn't matter.

Is something like this is possible?


回答1:


Sure. Declare a delegate in NSOperation subclass. Then after finish of operation

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

In UI

-(void)YourOperationDidFinish:(YourOperation *)downloader {
    if(downloader.downloadItem) {
        // processing with your object       
    }
}



回答2:


An alternative to the protocol-delegate pattern is a completion block. For example, in some random NSURLConnection based operation, I define a completion block typedef (just to simplify the block syntax later) that returns a NSData if successful, or an NSError if not:

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

I can then define a block property for my NSOperation subclass, e.g.:

@property (nonatomic, copy) CustomOperationCompletionBlock successFailureBlock;

I'll often have a rendition of my init method of my operation that will let me set that completion block during the init process (in addition to anything else I want to initialize):

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

My various methods that handle errors and/or success within my operation would then call that completion block to pass the data back:

- (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];
}

And, to use this operation with custom completion block handler, when I initiate my operation, I can just pass it a custom completion block. For example, this saves the data if successful, or logs the error if not:

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];

Clearly, you would change the block typedef to pass back whatever objects that make sense for your operation. But this illustrates the basic pattern of a block-based mechanism for a NSOperation subclass to return data.



来源:https://stackoverflow.com/questions/19373855/return-data-from-nsoperation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!