2014-04-28 12 views
5

Próbuję najlepiej sformatować wykorzystanie mojego projektu przez RestKit i Core Data. Jest kilka rzeczy, które mam działa, ale mam wrażenie, że są one źle zaimplementowane i potencjalnie niebezpieczne w wątkach ... Mam obiekt, który zarządza całą moją transmisją danych, pamięcią masową itp., Która ma funkcję który ustawia restkit. Mam zmienną instancji, której używam dla RKObjectManager, i w tej funkcji konfiguracyjnej tworzę obiekt objectStore, konfiguruję wszystkie mapowania atrybutów, tworzę stały magazyn itp., - cały normalny kod instalacji restkita. Poza tą funkcją jedyną rzeczą dostępną dla tego obiektu jest zmienna instancji _objectManager, której używałem dla NSFetchRequests i takie.RestKit i konteksty obiektów zarządzanych

Są dwie rzeczy, które chcę, aby upewnić się, że wdrażam prawidłowo, pobieranie zarządzanych obiektów i oszczędzanie zmian w zarządzanych obiektach.

Jeśli chcę zaktualizować właściwość na obiekcie, robiłem to:

object.whatever = @"something here"; 

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

Czy to właściwa droga do aktualizacji/zapisać właściwość na obiekcie? Czy dostęp do kontekstu obiektu zarządzanego obiektu jest zapisywany bezpośrednio w dowolnym punkcie kodu, czy jest to coś, co powinno być wykonane tylko w tle/planie? Moja obecna implementacja mogłaby potencjalnie wywołać to zarówno w tle, jak i na pierwszym planie, a ja po prostu chcę się upewnić, że jest to dopuszczalne.

Kiedy chcę, aby pobrać obiekt, napisałem funkcję, która pobiera nazwę podmiotu, tablicę orzeczników, a deskryptor sortowania jako parametry więc to może być ponownie wykorzystany:

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; 

Mój problem tutaj jest tworzenie/uzyskiwanie dostępu do poprawnego kontekstu obiektu zarządzanego. Jak mam to zrobić? Czy mogę uzyskać dostęp do niektórych nieruchomości na RKObjectManager utworzonego przed takimi jak:

_objectManager.managedObjectStore.mainQueueManagedObjectContext 

lub jest to, że nie wątku bezpieczne, ponieważ jej do głównego wątku? Co mogę zrobić, aby upewnić się, że używam właściwego kontekstu zarządzanego obiektu i że jest bezpieczny dla wątków? Używałem:

_objectManager.managedObjectStore.persistentStoreManagedObjectContext 

ale powiedziano mi, że to zdecydowanie nie najlepsze praktyki i nie wątku bezpieczne, więc staram się określić najlepsze rozwiązanie.

EDYCJA - może mogę wywołać tę funkcję, aby uzyskać kontekst, gdy chcę pobrać obiekty?

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

Odpowiedz

5

Dla oszczędności, zamiast tego:

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

należy zrobić:

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

tak, że zmiany są zachowywane aż łańcucha do sklepu na dysku. Powinieneś to robić tylko w wątku, który utworzył/pobrał zarządzany obiekt (w ten sposób zachowana jest własność wątku MOC).

Pierwszy plan/tło nie jest tak ważny, jak MOC jest używany przez każdy wątek. Jeśli prawa własności wątku MOC są przestrzegane, powinieneś być w porządku.

To samo dotyczy pobierania. W przypadku aktualizacji interfejsu użytkownika musisz użyć głównego wątku i mainQueueManagedObjectContext. Nigdy nie należy bezpośrednio korzystać z persistentStoreManagedObjectContext.W przypadku dowolnych wątków w tle powinieneś poprosić zarządzaną składnicę obiektów, aby utworzyła nowy kontekst obiektu podrzędnego dla obiektów zarządzanych dla Ciebie i używał go.

+0

Byłeś bardzo pomocny! Moim głównym problemem jest to, że funkcja ta jest tak ogólna, że ​​nie wie, na którym wątku jest uruchomiony. Czy jest jakiś prosty sposób na określenie tego, aby wiedzieć, czy użyć obiektu mainQueueManagedObjectContext, czy utworzyć nowy kontekst podrzędny? – Mike

+1

'[NSThread isMainThread]', ale nie można znaleźć, który z kilku wątków w tle może być. Czasami możesz użyć 'threadDictionary' do przechowywania tego rodzaju informacji ... – Wain

+0

Po prostu dodałem edycję powyżej, co według mnie spełnia te wymagania. Daj mi znać, jeśli ta prosta zmiana jest OK. – Mike

Powiązane problemy