Asynchronous methods in NSOperation

Michael Waterfall picture Michael Waterfall · Oct 20, 2009 · Viewed 15.7k times · Source

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

Answer

Jason Moore picture Jason Moore · Nov 5, 2015

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