Sto cercando di sincronizzare il seguente codice nel iOS5:Come dovrei usare GCD dispatch_barrier_async in iOS (sembra per eseguire prima e non dopo altri blocchi)
- un oggetto ha un metodo che effettua una richiesta HTTP da cui ottiene alcuni dati, tra cui un URL a un'immagine
- una volta arriva l'dati, i dati testuali viene utilizzato per popolare un modello CoreData
- , allo stesso tempo, un secondo thread viene inviato asincrona per scaricare l'immagine; questo thread segnala via KVO a un viewController quando l'immagine è già memorizzata nella cache e disponibile nel modello CoreData.
- poiché il download dell'immagine richiederà un po 'di tempo, restituiamo immediatamente l'oggetto CoreData che ha tutti gli attributi ma per l'immagine a il chiamante.
- Inoltre, al termine del download del secondo thread, è possibile salvare il modello CoreData .
Questo è il codice (semplificato):
- (void)insideSomeMethod
{
[SomeHTTPRequest withCompletionHandler:
^(id retrievedData)
{
if(!retrievedData)
{
handler(nil);
}
// Populate CoreData model with retrieved Data...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSURL* userImageURL = [NSURL URLWithString:[retrievedData valueForKey:@"imageURL"]];
aCoreDataNSManagedObject.profileImage = [NSData dataWithContentsOfURL:userImageURL];
});
handler(aCoreDataNSManagedObject);
[self shouldCommitChangesToModel];
}];
}
- (void)shouldCommitChangesToModel
{
dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSError *error = nil;
if(![managedObjectContext save:&error])
{
// Handle error
}
});
}
Ma quello che sta succedendo è che la barriera a base di Save-blocco viene sempre eseguito prima del blocco dell'immagine di caricamento. Cioè,
dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSError *error = nil;
if(![managedObjectContext save:&error])
{
// Handle error
}
});
eseguito prima:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSURL* userImageURL = [NSURL URLWithString:[retrievedData valueForKey:@"imageURL"]];
aCoreDataNSManagedObject.profileImage = [NSData dataWithContentsOfURL:userImageURL];
});
Così, ovviamente, non sto davvero dispacciamento del blocco di caricamento delle immagini prima della barriera, o la barriera avrebbe aspettato fino a quando il blocco di caricamento delle immagini è fatto prima dell'esecuzione (quale era la mia intenzione).
Cosa sto sbagliando? come posso essere sicuro che il blocco di caricamento dell'immagine sia accodato prima del blocco barriera?
Ci ho pensato più volte ma poi, non i documenti Apple affermano che in iOS non possiamo davvero creare le nostre code? In modo che se io "creo" uno in realtà sto solo ottenendo un alias su uno di quelli globali? – SaldaVonSchwartz
Credo che da iOS5 sia possibile creare le code di invio. – timthetoolman
Sì, l'ho appena provato e ora funziona. Avrei giurato di aver letto che non saremmo riusciti a crearne di propri o che la creazione li ha semplicemente restituito uno di quelli globali, motivo per cui ho scelto uno globale nel mio codice. – SaldaVonSchwartz