Return data from NSOperation?

I create a lot of NSOperation (subclasses) that sort through a bunch of data. When they end, I would like them to β€œreturn” this data and put it in a mutable array or something like that. The order does not matter.

Is this possible?

+6
ios objective-c nsoperation
Oct 15 '13 at 5:25
source share
2 answers

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

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

In user interface

 -(void)YourOperationDidFinish:(YourOperation *)downloader { if(downloader.downloadItem) { // processing with your object } } 
+4
Oct. 15 '13 at 5:31 on
source share

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

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

Then I can define a block property for my NSOperation subclass, for example:

 @property (nonatomic, copy) CustomOperationCompletionBlock successFailureBlock; 

I will often have the execution of my init method of my operation, which will allow me to set this completion block during the init process (in addition to everything I want to initialize):

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

My various methods that handle errors and / or success in my operation then call this 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 a custom completion block handler, when I start my operation, I can just pass it a custom completion block. For example, it saves data if successful or logs an 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]; 

Obviously, you would modify the typedef block to pass all the objects that make sense to your operation. But this illustrates the basic block mechanism template for a subclass of NSOperation to return data.

+14
Oct. 15 '13 at 6:25
source share



All Articles