2012-10-19 20 views
5

Attualmente sto usando GCD. Tuttavia, ho sentito che NSOperation è in realtà un programma di livello superiore. È molto più complesso però.Quale è più facile da usare? GCD o NSOperation?

In GCD, fare qualcosa in fondo è sufficiente utilizzare questa funzione di supporto che ho creato:

+(void)doForeGround:(void (^)())block 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     block(); 
    }); 
} 

+(void)doBackground:(void (^)())block 
{ 

    //DISPATCH_QUEUE_PRIORITY_HIGH 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{ 
    //dispatch_async(dispatch_get_global_queue(-2,0), ^{ 
     block(); 
    }); 
} 

-(void)doBackGround:(void (^)())block onComletion:(void (^)())onCompletion 
{ 
    [BGHPTools doBackground:^{ 
     block(); 
     [BGHPTools doForeGround:^{ 
      onCompletion(); 
     }]; 
    }]; 
} 

Will farlo con NSOperation essere più semplice?

Mi manca qualcosa? Come dovrei fare la stessa cosa a NSoperation?

risposta

6

Si possono fare cose simili con NSOperation come si sta facendo con GCD. La differenza principale è che NSOperation fornisce funzionalità aggiuntive.

Ad esempio:

  • NSOperation ha un metodo -cancel. Le code di spedizione non hanno alcun concetto di cancellazione; tutti i blocchi inseriti in coda verranno eseguiti fino alla fine.
  • NSOperationQueue ha una proprietà maximumConcurrentOperationCount, che è possibile utilizzare (ad esempio) per consentire l'esecuzione di sole 3 operazioni alla volta. Le code di invio non hanno questo concetto; sono entrambi seriali, consentendo solo 1 blocco alla volta, o simultanei, consentendo di considerare fino a libdispatch in base all'utilizzo e alla disponibilità della CPU.
  • Un NSOperation può avere una dipendenza da altri NSOperation s, consentendo di rinviare l'esecuzione di una particolare operazione fino a quando tutte le sue dipendenze sono state eseguite. Altre operazioni consentiranno di "saltare avanti" nella coda mentre l'operazione dipendente è in attesa. Le code di invio vengono sempre ritirate dalla coda nell'ordine strettamente FIFO. (Si può in qualche modo imitare le dipendenze utilizzando l'API dispatch_group, ma questo è in realtà destinati a un diverso tipo di problema.)

Ora, se non si sta usando nessuna di queste caratteristiche, GCD funziona bene. Non c'è nulla errato con l'utilizzo di GCD, di per sé. È solo che NSOperation fornisce un comodo wrapper per alcune funzionalità aggiuntive.

Ecco come si sarebbe riscrivere l'esempi sopra utilizzando NSOperationQueue:

+(void)doForeground:(void (^)())block 
{ 
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
     NSLog(@"I'm running on the main thread!"); 
     block(); 
    }]; 
} 

+(void)doBackground:(void (^)())block 
{ 
    // Note; rather than allocating a new NSOperationQueue every time, you could 
    // allocate the queue once and just refer to that queue. For simplicity, I'll 
    // skip that here. 
    [[NSOperationQueue new] addOperationWithBlock:^{ 
     NSLog(@"I'm running asynchronously on whatever thread NSOperationQueue wants!"); 
     block(); 
    }]; 
} 

-(void)doBackground:(void (^)())block onCompletion:(void (^)())onCompletion 
{ 
    [[NSOperationQueue new] addOperationWithBlock:^{ 
     block(); 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      onCompletion(); 
     }]; 
    }]; 
} 
+0

E suppongo che NSOperation crei anche i propri stack di autorelease annidati? –

+0

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html non descrive un metodo chiamato nuovo. Ah deve essere quella scorciatoia per alloc] init] –

+0

'+ new' è ereditato da' NSObject', proprio come alloc e init. E sì, il blocco di ogni operazione vivrà in un pool di autorelease. –

4

Un esempio coda di funzionamento per il confronto:

- (void)viewDidLoad 
{ 
    // ... 

    self.queue = [[NSOperationQueue alloc] init]; 

    // ... 
} 

- (void)job 
{ 
    // background activities ... 
} 

- (void)startJob 
{ 
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self 
                    selector:@selector(job) 
                    object:nil]; 
    [self.queue addOperation:op]; 
} 
+1

Mi piace usare blocchi :) –

+1

Naturalmente uno comunque. –