Search code examples
iosobjective-cnsoperationnsoperationqueue

AsyncTask implementation using NSOperation in iOS


I implemented AsyncTask(Android) in iOS using NSOperation subclass.

-(id)initWithParam:(NSArray *)params{

if (self = [super init]) {

paramsArray = params;
}
return self;

}

- (void)start {

         @autoreleasepool {

   if (self.isCancelled)
      return;
   NSInteger result;

   result = [self doInBackground:paramsArray];

dispatch_async(dispatch_get_main_queue(), ^{

    [self postExecute:result];
});
}
}


 - (BOOL) doInBackground: (NSArray *) parameters{

   BOOL status = false;
   int i;
 for (i=0; i<100000; i++) {
     NSLog(@"printing i::%d",i);
 }
 if (i == 100000) {
    status = YES;
 }

return status;
}
- (void) postExecute: (BOOL) deviceState{

   if (deviceState) {
      NSLog(@"Finished");
  }

}

-(BOOL)isConcurrent{

   return YES;
}

This is the way I implemented in iOS.Please suggest and any thing I want to add for this functionality.

And also, when can I call isExecuting and isFinished in NSOperation subclass


Solution

  • In answer to your question, unfortunately, no, this implementation is not correct. Close, but not quite there.

    A couple of things:

    1. Your example is not concurrent operation. In the case of NSOperation, the term "concurrent operation" (now called an "asynchronous operation") has a special meaning. An asynchronous operation is one that that continues to run asynchronously even after the start method finishes. And you designate this by returning YES from isConcurrent (in older iOS versions) and isAsynchronous (in contemporary iOS versions). But the example operation in the question is completely done when start ends, so therefore is not an asynchronous operation and therefore isConcurrent and isAsynchronous should therefore return NO.

      Let's assume in this example that you changed isConcurrent to return NO, as would be appropriate with what you're performing in start. That would fix this operation. But don't let this confuse you. If you added this operation to your own operation queue, it would still run asynchronously/concurrently with respect to the main queue, it's just that it's an operation that automatically finishes when start finishes, and therefore isAsynchronous/isConcurrent should return NO.

    2. You ask "when can I call isExecuting and isFinished?" Well, you generally don't call those methods. You generally implement those methods. Specifically, when an asynchronous operation eventually finishes, you must ensure that the app (a) posts KVN for the isExecuting and isFinished keys; and (b) you override isExecuting and isFinished to ensure that they correspondingly return the appropriate values.

      You only have to implement this isExecuting and isFinished code when the operation is truly an asynchronous/concurrent operation. See the Configuring Operations for Concurrent Execution section of the Concurrency Programming Guide: Operation Queues. Also see the introductory section of the NSOperation class definition.

    Whether your operation should be asynchronous or not (or even whether you need to subclass NSOperation at all) is unclear. It depends entirely upon what task you want to perform, and whether the task itself runs asynchronously or not.