2009-10-20 14 views
31

Sto recuperando alcuni dati da Facebook Connect (utilizzando il framework FBConnect Objective-C 2.0) e sto facendo tutto ciò in una NSOperation. È in una NSOperation perché ho diverse altre operazioni che funzionano pure e questa è una di queste.Metodi asincroni in NSOperation

Il problema è che tutte le chiamate FBConnect sono asincrone. Per questo motivo, il metodo principale di NSOperation termina rapidamente e l'operazione viene contrassegnata come completata.

C'è un modo per superare questo? Sembrerebbe che non ci siano opzioni sincrone in FBConnect!

Molte grazie,

Mike

+0

Se 'FBConnect' è intrinsecamente asincrono, c'è davvero bisogno di usare un' NSOperation'? –

+1

Sì, perché è una delle tante attività in coda e c'è molta elaborazione che si verifica dopo il download dei dati. –

+2

Perché non creare il 'NSOperation' per quella elaborazione una volta completato il download asincrono, quindi? –

risposta

6

mettere le chiamate in FBConnect 'start', non e 'main', e gestire le proprietà 'isFinished' 'isExecuting'. (e restituire YES per "isConcurrent")

Per ulteriori dettagli, consultare la documentazione di Apple sulla scrittura concurrent NSOperations.

+3

A partire da iOS 7.0, deve essere usato 'isAsynchronous' invece di' isConcurrent'. –

22

Di seguito è riportato un esempio completo. Nella sottoclasse, una volta completato il metodo asincrono, chiamare [self completeOperation] per passare allo stato completato.

@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 
+0

ottima risposta !!! – eric

+0

Detto questo ... per altri usi, come forse una classe che sottoclassi NSObject, e gestisce NSOperationQueue per te ... assicurati di impl: - (void) observValueForKeyPath: (NSString *) keyPath ofObject: (id) opporsi \t \t \t \t \t \t cambiamento: (NSDictionary *), modificare il contesto: (void *) contesto – eric

+1

Argh. No semplicemente no. Non definire le proprietà che iniziano con _. Ridefinire le proprietà esistenti. Chiama "super" se è necessario. –

Problemi correlati