[objective-c] Alternative a dispatch_get_current_queue () per i blocchi di completamento in iOS 6?



Answers

Questo è fondamentalmente l'approccio sbagliato per l'API che stai descrivendo. Se un'API accetta un blocco e un blocco di completamento da eseguire, i seguenti fatti devono essere veri:

  1. Il "blocco da eseguire" deve essere eseguito su una coda interna, ad esempio una coda privata dell'API e quindi interamente sotto il controllo di tale API. L'unica eccezione è se l'API dichiara esplicitamente che il blocco verrà eseguito sulla coda principale o su una delle code simultanee globali.

  2. Il blocco di completamento dovrebbe sempre essere espresso come una tupla (coda, blocco) a meno che le stesse supposizioni di # 1 siano valide, ad esempio il blocco di completamento verrà eseguito su una coda globale nota. Il blocco di completamento dovrebbe inoltre essere inviato async sulla coda passata.

Questi non sono solo punti stilistici, sono assolutamente necessari se la tua API deve essere al sicuro da deadlock o altri comportamenti edge-edge che altrimenti ti impiccheranno dall'albero più vicino un giorno. :-)

Question

Ho un metodo che accetta un blocco e un blocco di completamento. Il primo blocco dovrebbe essere eseguito in background, mentre il blocco di completamento dovrebbe essere eseguito in qualsiasi coda il metodo è stato chiamato.

Per quest'ultimo ho sempre usato dispatch_get_current_queue() , ma sembra che sia deprecato in iOS 6 o versioni successive. Cosa dovrei usare invece?




Dovresti stare attento al tuo uso di dispatch_get_current_queue in primo luogo. Dal file di intestazione:

Consigliato solo per il debug e la registrazione:

Il codice non deve formulare alcuna ipotesi sulla coda restituita, a meno che non sia una delle code globali o una coda creata dal codice stesso. Il codice non deve presumere che l'esecuzione sincrona su una coda sia al sicuro da deadlock se tale coda non è quella restituita da dispatch_get_current_queue ().

Potresti fare una delle due cose:

  1. Tieni un riferimento alla coda originariamente pubblicata su (se l'hai creata tramite dispatch_queue_create ), e usala da quel momento in poi.

  2. Utilizza le code definite dal sistema tramite dispatch_get_global_queue e mantieni traccia di quale stai utilizzando.

Effettivamente, mentre prima facevi affidamento sul sistema per tenere traccia della coda in cui ti trovi, dovrai farlo da solo.




Apple aveva deprecato dispatch_get_current_queue() , ma ha lasciato un buco in un altro posto, quindi è ancora possibile ottenere la coda di invio corrente:

if let currentDispatch = OperationQueue.current?.underlyingQueue {
    print(currentDispatch)
    // Do stuff
}

Funziona almeno per la coda principale. Nota che la proprietà underlyingQueue è disponibile da iOS 8.

Se è necessario eseguire il blocco di completamento nella coda originale, è possibile utilizzare direttamente OperationQueue , ovvero senza GCD.




Links