2014-04-28 12 views
5

Sto provando a formattare al meglio l'uso del mio progetto su RestKit e Core Data. Ci sono un paio di cose su cui ho lavorato, ma ho la sensazione che siano implementate male e potenzialmente non sono sicure ... Ho un oggetto che gestisce tutto il mio trasferimento di dati, archiviazione, ecc., Che ha una funzione che costituisce il restkit. Ho una variabile di istanza che utilizzo per RKObjectManager e in questa funzione di installazione creo objectStore, imposto tutti i mapping degli attributi, creo l'archivio permanente, ecc., Tutto il normale codice di configurazione del restkit. Al di fuori di questa funzione, l'unica cosa disponibile per questo oggetto è la variabile di istanza _objectManager, che ho utilizzato per NSFetchRequests e così via.Contesti oggetto RestKit e gestito

Ci sono due cose che voglio assicurarmi che sto implementando correttamente, recuperando oggetti gestiti e risparmi sulle modifiche agli oggetti gestiti.

Se voglio aggiornare una proprietà su un oggetto, ho fatto questo:

object.whatever = @"something here"; 

NSError *error; 
if (![object.managedObjectContext save:&error]) { 
    // log the error here 
} 

E 'questo il modo corretto per aggiornare/salvare una proprietà su un oggetto? L'accesso al contesto dell'oggetto gestito dell'oggetto si salva direttamente in qualsiasi punto del codice, oppure è qualcosa che dovrebbe essere fatto solo in background/in primo piano? La mia attuale implementazione potrebbe potenzialmente aver richiamato sia lo sfondo che il primo piano e voglio solo assicurarmi che sia accettabile.

Quando voglio andare a prendere un oggetto, ho scritto una funzione che prende il nome di un'entità, una serie di predicati, e un descrittore di sorta come parametri in modo che possa essere riutilizzato:

NSManagedObjectContext *managedObjectContext = // I DONT KNOW WHAT TO PUT HERE! // 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 

    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates]; 
    [fetchRequest setPredicate:compoundPredicate]; 

    NSError *error; 
    NSArray *fetchedRecords = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; 

    if (error) { 
     // log error 
    } 

    // if we were given a sort descriptor, sort the array appropriately 
    if (sortDescriptor) { 
     fetchedRecords = [fetchedRecords sortedArrayUsingDescriptors:@[sortDescriptor]]; 
    } 

    return fetchedRecords; 

Il mio problema qui è creazione/accesso al contesto dell'oggetto gestito corretto. Come dovrei farlo? Faccio ad accedere alcune proprietà sul RKObjectManager ho creato prima come ad esempio:

_objectManager.managedObjectStore.mainQueueManagedObjectContext 

o è che non thread-safe perché la sua per il thread principale? Cosa posso fare per assicurarmi di utilizzare il contesto dell'oggetto gestito corretto e che sia thread-safe? Stavo usando:

_objectManager.managedObjectStore.persistentStoreManagedObjectContext 

ma mi è stato detto che questo era sicuramente non è delle migliori pratiche e non è stato thread-safe, quindi sto cercando di determinare la soluzione migliore.

EDIT - forse posso chiamare questa funzione per ottenere il contesto ogni volta che voglio recuperare oggetti?

- (NSManagedObjectContext *)getManagedObjectContext { 
    if ([NSThread isMainThread]) { 
     return _objectManager.managedObjectStore.mainQueueManagedObjectContext; 
    } 
    else { 
     return [_objectManager.managedObjectStore newChildManagedObjectContextWithConcurrencyType:NSPrivateQueueConcurrencyType tracksChanges:YES]; 
    } 
} 

risposta

5

Per risparmiare, invece di questo:

if (![object.managedObjectContext save:&error]) { 

si dovrebbe fare:

if (![object.managedObjectContext saveToPersistentStore:&error]) { 

modo che le modifiche vengono mantenute fino alla catena al negozio on-disk. Si dovrebbe fare solo questo sul thread che ha creato/recuperato l'oggetto gestito (quindi viene mantenuta la proprietà del thread del MOC).

Primo piano/sfondo non è importante quanto il MOC utilizzato da ciascun thread. Se la proprietà del thread MOC è rispettata, si dovrebbe andare bene.

Lo stesso vale per il recupero. Per gli aggiornamenti dell'interfaccia utente, è necessario utilizzare il thread principale e lo mainQueueManagedObjectContext. Non si dovrebbe mai usare direttamente lo persistentStoreManagedObjectContext.Per i thread di sfondo arbitrari dovresti chiedere all'archivio oggetti gestito di creare un nuovo contesto di oggetti gestito dall'infanzia per te e utilizzarlo.

+0

Sei stato estremamente utile! Il mio problema principale è che questa funzione è stata creata in modo così generico da non sapere su quale thread è in esecuzione. C'è un modo semplice per determinare questo in modo che io possa sapere se utilizzare mainQueueManagedObjectContext o creare un nuovo contesto figlio? – Mike

+1

'[NSThread isMainThread]', ma non per trovare quale dei vari thread in background potresti avere. A volte puoi usare 'threadDictionary' per memorizzare questo tipo di informazioni ... – Wain

+0

Ho appena aggiunto una modifica sopra per quello che penso soddisfi quei requisiti. Fammi sapere se questo semplice cambiamento è OK. – Mike