Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous methods in NSOperation

I'm fetching some data from Facebook Connect (using the FBConnect Objective-C 2.0 framework) and I'm doing all that in an NSOperation. It is in an NSOperation because I have several other operations that run as well and this is one of them.

The problem is that all the FBConnect calls are asynchronous. Because of this, the main method of the NSOperation quickly finishes and the operation is marked as completed.

Is there some way to overcome this? It would appear there are no synchronous options in FBConnect!

Many thanks,

Mike

like image 724
Michael Waterfall Avatar asked Oct 20 '09 17:10

Michael Waterfall


People also ask

What is asynchronous operation in Swift?

Asynchronous operations allow executing long-running tasks without having to block the calling thread until the execution completes. It's a great way to create separation of concern, especially in combination with creating dependencies in-between operations.

What is NSOperation?

An abstract class that represents the code and data associated with a single task.

What is the difference between NSOperationQueue and GCD?

GCD is a low-level C-based API that enables very simple use of a task-based concurrency model. NSOperation and NSOperationQueue are Objective-C classes that do a similar thing. NSOperation was introduced first, but as of 10.5 and iOS 2, NSOperationQueue and friends are internally implemented using GCD .

What is NSOperationQueue in Swift?

A queue that regulates the execution of operations.


2 Answers

Below is a full example. In your subclass, after your async method completes, call [self completeOperation] to transition to the finished state.

@interface AsynchronousOperation() // 'executing' and 'finished' exist in NSOperation, but are readonly @property (atomic, assign) BOOL _executing; @property (atomic, assign) BOOL _finished; @end  @implementation AsynchronousOperation  - (void) start; {     if ([self isCancelled])     {         // Move the operation to the finished state if it is canceled.         [self willChangeValueForKey:@"isFinished"];         self._finished = YES;         [self didChangeValueForKey:@"isFinished"];         return;     }      // If the operation is not canceled, begin executing the task.     [self willChangeValueForKey:@"isExecuting"];     [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];     self._executing = YES;     [self didChangeValueForKey:@"isExecuting"];  }  - (void) main; {     if ([self isCancelled]) {         return;     }  }  - (BOOL) isAsynchronous; {     return YES; }  - (BOOL)isExecuting {     return self._executing; }  - (BOOL)isFinished {     return self._finished; }  - (void)completeOperation {     [self willChangeValueForKey:@"isFinished"];     [self willChangeValueForKey:@"isExecuting"];      self._executing = NO;     self._finished = YES;      [self didChangeValueForKey:@"isExecuting"];     [self didChangeValueForKey:@"isFinished"]; }  @end 
like image 138
Jason Moore Avatar answered Nov 07 '22 04:11

Jason Moore


put your FBConnect calls in 'start', not 'main', and manage the 'isFinished' 'isExecuting' properties. (and return YES for 'isConcurrent')

For more details, see Apple's documentation on writing concurrent NSOperations.

like image 35
Roy Lovejoy Avatar answered Nov 07 '22 03:11

Roy Lovejoy