2013-10-22 10 views
5

Ho cercato di utilizzare dispatch_async in un metodo che restituisce un risultato. Tuttavia, ho osservato che il metodo ritorna prima di eseguire il blocco dispatch_async. A causa di ciò, non sto ottenendo i risultati che mi aspetto. Ecco un codice che dimostra il mio problema.dispatch_async in modalità ritorno obiettivo c

-(BOOL) isContactExists { 
    BOOL isContactExistsInXYZ = YES; 
    UserId *userId = contact.userId; 
    dispatch_async(dispatch_get_main_queue(),^
    { 
     iOSContact *contact = [iOSContact contactForUserId:userId]; 
     if (nil == contact) 
     { 
      isContactExistsInXYZ = NO; 
     } 
    });  

    return isContactExistsInXYZ; 
} 

Questo metodo isContactExists viene chiamato da qualche altra parte e si basa sulla risposta da quel metodo devo fare alcune cose. Ma ogni volta, il valore di isContactExistsInXYZ non è quello che mi aspetto. Qualcuno può spiegare come gestire dispatch_async in questa situazione?

Grazie.

+0

dispatch_async è asincrona è media che yhe ritorno sarà raggiunto entro la fine della spedizione asincrona – Francescu

+0

@ Francescu, che ho capito con la mia analisi si può per favore aiutatemi a come gestire la cosa in altro modo, un frammento di codice o informazioni logiche. Grazie –

risposta

6

È necessario rispettare ciò che si sta tentando di fare è asincrono e abbracciarlo. Questo significa non usare un valore di ritorno. Invece puoi scrivere il tuo metodo per prendere un blocco di callback come parametro. Quindi, una volta completato il controllo asincrono, puoi chiamare il blocco con il risultato.


Così la vostra firma del metodo sarebbe diventato:

- (void)checkIfContactExistsWithCompletion:(ContactExistsBlock)completion { 

Dove ContactExistsBlock è una definizione di blocco senza ritorno e, probabilmente, un singolo parametro BOOL.

typedef void (^ContactExistsBlock) (BOOL exists); 
+0

Si può elaborare con un codice di esempio o mi stai dicendo di utilizzare il blocco "completamento gestore" –

3

Il motivo è dispatch_async(dispatch_get_main_queue(), ^ non attende fino al termine dell'esecuzione. Probabilmente stai rovinando cose lì. Normalmente, questo viene utilizzato per aggiornare l'interfaccia utente in modo asincrono insieme ad altri contenuti del server scaricati in qualche altro thread. Prova a utilizzare dispatch_sync invece.

+0

Qui una cosa che devo menzionare è che il mio requisito è che devo eseguire l'operazione in background thread, quindi ho scelto di usare 'dispatch_async' su' dispatch_sync'. Puoi per favore procurarmi una informazione logica o gestirla in altro modo. Grazie. –

+0

È necessario esaminare il modello di delega. Ci sono molti esempi nel framework iOS. Guarda come funziona NSConnection. Ti dà una chiamata non appena un chunk di dati è pronto. Quindi, probabilmente, è necessario eseguire l'operazione in modo asincrono e quindi gestire la chiamata attraverso i metodi delegati. – Abhinav

10

Se stai seguendo il percorso a blocchi, il tuo metodo deve essere simile a questo.

- (void)isContactExistsWithCompletionHandler:(void(^)(BOOL exists)) completion 
{ 
    dispatch_async(dispatch_get_main_queue(),^
    { 
     BOOL isContactExistsInXYZ = YES; 
     UserId *userId = contact.userId; 
     iOSContact *contact = [iOSContact contactForUserId:userId]; 
     if (nil == contact) 
     { 
      isContactExistsInXYZ = NO; 
     } 
     completion(isContactExistsInXYZ); 
    }); 
} 

E dove lo si chiama qualcosa del genere.

[someObject isContactExistsWithCompletionHandler:^(BOOL exists) { 
    // do something with your BOOL 
}]; 

Si dovrebbe anche considerare mettendo le operazioni pesanti in un altro que quello principale. Come questo.

- (void)isContactExistsWithCompletionHandler:(void(^)(BOOL exists)) completion 
{ 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL); 
    dispatch_async(queue,^
    { 
     BOOL isContactExistsInXYZ = YES; 
     UserId *userId = contact.userId; 
     iOSContact *contact = [iOSContact contactForUserId:userId]; 
     if (nil == contact) 
     { 
      isContactExistsInXYZ = NO; 
     } 
     dispatch_async(dispatch_get_main_queue(),^
     { 
      completion(isContactExistsInXYZ); 
     }); 
    }); 
}