2014-04-28 5 views
5

Ich versuche, die Verwendung von RestKit und Core Data in meinem Projekt am besten zu formatieren. Es gibt ein paar Dinge, die ich habe funktioniert, aber ich habe das Gefühl, sie sind schlecht implementiert und potenziell Thread unsicher ... Ich habe ein Objekt, das alle meine Datenübertragung, Speicher usw., die eine Funktion hat verwaltet das baut Restkit auf. Ich habe eine Instanzvariable, die ich für RKObjectManager benutze, und in dieser Setup-Funktion erstelle ich den Objektspeicher, richte alle Attribut-Zuordnungen ein, erstelle den persistenten Speicher usw. - alles normale Setup-Code des Restkits. Außerhalb dieser Funktion ist für dieses Objekt nur die Instanzvariable _objectManager verfügbar, die ich für NSFetchRequests usw. verwendet habe.Kontexte von RestKit und verwalteten Objekten

Es gibt zwei Dinge, die ich sicherstellen möchte, dass ich ordnungsgemäß implementiere, verwaltete Objekte abrufe und Änderungen an verwalteten Objekten einspare. eine Eigenschaft auf ein Objekt zu aktualisieren/speichern

object.whatever = @"something here"; 

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

Ist dies der richtige Weg:

Wenn ich eine Eigenschaft auf ein Objekt aktualisiert werden soll, habe ich das getan? Ist der Zugriff auf den Objektkontext des Objekts direkt möglich, um ihn an irgendeiner Stelle im Code zu speichern, oder sollte dies nur im Hintergrund/Vordergrund geschehen? Meine aktuelle Implementierung könnte dies möglicherweise sowohl im Hintergrund als auch im Vordergrund aufgerufen haben und ich möchte nur sicherstellen, dass dies akzeptabel ist.

Wenn ich ein Objekt holen will, schrieb ich eine Funktion, die eine Entität Namen hat, eine Reihe von Prädikaten, und eine Art Descriptor als Parameter, so kann es wieder verwendet werden:

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; 

Mein Problem hier ist, Erstellen/Zugreifen auf den richtigen verwalteten Objektkontext. Wie soll ich das machen? Greife ich auf ein Grundstück auf dem RKObjectManager ich vor wie geschaffen:

_objectManager.managedObjectStore.mainQueueManagedObjectContext 

oder ist das, weil sie für den Haupt-Thread nicht Thread-sicher? Was kann ich tun, um sicherzustellen, dass ich den richtigen Kontext für das verwaltete Objekt verwende und dass es threadsicher ist? Ich war mit:

_objectManager.managedObjectStore.persistentStoreManagedObjectContext 

aber mir wurde gesagt, dies war auf jeden Fall nicht best practice und wurde nicht Thread sicher, so versuche ich, die beste Lösung zu bestimmen.

EDIT - vielleicht kann ich diese Funktion aufrufen, um den Kontext zu erhalten, wann immer ich Objekte holen will?

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

Antwort

5

Für Einsparung, statt dies:

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

sollten Sie tun:

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

, damit die Änderungen bis die Kette auf den On-Disk-Speicher beibehalten werden. Sie sollten dies nur für den Thread tun, der das verwaltete Objekt erstellt/abgerufen hat (somit wird die Thread-Eigentümerschaft des MOC beibehalten).

Vordergrund/Hintergrund ist nicht so wichtig wie MOC von jedem Thread verwendet wird. Wenn der Besitz des MOC-Gewindes respektiert wird, sollte alles in Ordnung sein.

Gleiches gilt für das Abrufen. Für UI-Updates müssen Sie den Hauptthread und die mainQueueManagedObjectContext verwenden. Sie sollten niemals direkt die persistentStoreManagedObjectContext verwenden.Bei beliebigen Hintergrundthreads sollten Sie den verwalteten Objektspeicher bitten, einen neuen untergeordneten Kontext für verwaltete Objekte für Sie zu erstellen und diesen zu verwenden.

+0

Sie waren sehr hilfreich! Mein Hauptproblem ist, dass diese Funktion so generisch gemacht wurde, dass sie nicht weiß, auf welchem ​​Thread sie läuft. Gibt es eine einfache Möglichkeit, dies zu bestimmen, damit ich weiß, ob ich den mainQueueManagedObjectContext verwenden oder einen neuen untergeordneten Kontext erstellen soll? – Mike

+1

'[NSThread isMainThread]', aber nicht, um welchen der verschiedenen Hintergrundthreads zu ermitteln. Manchmal können Sie 'threadDictionary' verwenden, um diese Art von Informationen zu speichern ... – Wain

+0

Ich habe gerade eine Bearbeitung hinzugefügt, die meiner Meinung nach diese Anforderungen erfüllt. Lassen Sie mich wissen, ob diese einfache Änderung in Ordnung ist. – Mike

Verwandte Themen