问题
I'm creating a lot of NSOperation
s (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