2012-08-16 7 views
27

Mam app z dwóch kontekstach zarządzanego obiektu konfiguracji jak poniżej:Podstawowe dane: Czy konteksty potomne otrzymują stałe identyfikatory obiektów dla nowo wstawionych obiektów?

  • nadrzędna kontekstu: NSPrivateQueueConcurrencyType, związanym z przetrwałym sklepie.
  • Główny kontekst: NSMainQueueConcurrencyType, element potomny kontekstu nadrzędnego.

Po włożeniu nowej zarządzanego obiektu do głównego kontekście zapisać główny kontekst, a następnie kontekście rodzic tak:

[context performBlockAndWait:^{ 
    NSError * error = nil; 
    if (![context save: &error]) { 
     NSLog(@"Core Data save error %@, %@", error, [error userInfo]); 
    } 
}]; 

[parentContext performBlock:^{ 
    NSError *error = nil; 
    BOOL result = [parentContext save: &error]; 
    if (! result) { 
     NSLog(@"Core Data save error in parent context %@, %@", error, [error userInfo]); 
    } 
}]; 

Moje zrozumienie jest, że gdy zarządzać obiekt jest stworzony, to ma tymczasowy objectID. Następnie główny kontekst zostaje zapisany i ten obiekt, wraz z jego tymczasowym ID, dostaje się do kontekstu nadrzędnego. Następnie zapisywany jest kontekst nadrzędny. Gdy ten ostatni kontekst zostanie zapisany, tymczasowy objectID w kontekście nadrzędnym zostanie przekształcony w trwały objectID.

Więc:

  • Czy stały identyfikator obiektu kiedykolwiek propagowane automatycznie z powrotem do głównego (dziecko) kontekście?
  • Kiedy zmusić, aby uzyskać obiekt stały identyfikator z [NSManagedObjectContext obtainPermanentIDsForObjects:error:], potem tle aplikację, reaktywować, przeładować, uzyskać obiektu przy głównym kontekst użytkownika objectWithID:, a dostęp do właściwości, mam

    „CoreData mógł nie spełnia winy za ... ".

Co jest nie tak z tym podejściem?

+0

Jorge: Dostaję CoreData nie może spełnić błędu, gdy uzyskuję stały identyfikator w kontekście podrzędnym i zapisuję obiekt ManagedObject. Czy dowiedziałeś się, z jakiego powodu? Dzięki –

Odpowiedz

40

Jest to znany bug, mam nadzieję, że wkrótce naprawione, ale w ogóle, uzyskanie stałego identyfikatora jest wystarczające, o ile to zrobić przed zapisaniem danych w pierwszym dzieckiem, a ty tylko to wstawione obiekty:

[moc obtainPermanentIDsForObjects:moc.insertedObjects.allObjects error:&error] 

W niektórych skomplikowanych przypadkach lepiej jest uzyskać stały identyfikator zaraz po utworzeniu instancji, zwłaszcza jeśli masz złożone relacje.

Jak i kiedy dzwonisz pod numer obtainPermanentIDsForObjects?

Nie śledzę części dotyczącej awarii aplikacji. Może mogłoby pomóc lepsze wyjaśnienie.

+0

Nie ma nic w ustawieniu moc.insertedObjects. Zgaduję, że zostanie to wyczyszczone po zapisaniu? Co robię, to zapisywanie wyboru użytkownika dokumentów, gdy aplikacja jest w tle. Aplikacja może aktualizować te, gdy jest w tle. Po przejściu na pierwszy plan zostaje odtworzony kontekst, a wybór zostaje przywrócony za pomocą identyfikatorów obiektów. Jednak przed przejściem do pracy w tle nowo utworzone dokumenty mają tymczasowe identyfikatory nawet po zapisaniu kontekstu. Jeśli wymuszam uzyskiwanie stałych identyfikatorów dla tych osób, po ponownym uruchomieniu aplikacji nie będzie można odtworzyć zarządzanych obiektów. – Jorge

+1

Tak, obiekt inserObjects zawiera tylko obiekty, które zostały wstawione i nie zostały zapisane. Nawet po podaniu im stałych identyfikatorów pozostaną one w insertObjects, dopóki nie zostaną zapisane. Spróbuj zapisać kontekst swojego dziecka przed zapisaniem. Powinien pobierać identyfikatory, a następnie propagować zapis na ich podstawie. Upewnij się, że zapisałeś w pełni wszystkie konteksty do bazy danych. –

+0

Uzyskanie identyfikatorów tuż przed zapisaniem rozwiązało problem. Dzięki! – Jorge

8

Jak powiedział Jody powyżej, przy tworzeniu nowego NSManagedObject w wątku tła przy użyciu dziecko ManagedObjectContext trzeba wymusić utworzenie stałego ID wykonując następujące warunki przed zapisać:

NSError *error = nil; 

[threadedMOC obtainPermanentIDsForObjects:threadedMOC.insertedObjects.allObjects error:&error]; 

BOOL success = [threadedMOC save:&error]; 

IMHO, to nie bardzo intuicyjne, aby zrobić to w ten sposób - mimo wszystko, pytasz o stałą identyfikację ZANIM uratujesz! Ale tak to wygląda, jak się wydaje. Jeśli poprosisz o stały identyfikator po zapisie, identyfikator będzie nadal tymczasowy.Z Apple Docs, rzeczywiście można użyć następujących celu ustalenia, czy identyfikator obiektu jest tymczasowy:

BOOL isTemporary = [[managedObject objectID] isTemporaryID]; 
1

Problem nadal istnieje w iOS 8.3 rozwiązanie w SWIFT:

func saveContext(context: NSManagedObjectContext?){ 
    NSOperationQueue.mainQueue().addOperationWithBlock(){ 
    if let moc = context { 
     var error : NSError? = nil 
     if !moc.obtainPermanentIDsForObjects(Array(moc.insertedObjects), error: &error){ 
      println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)") 
     } 
     if moc.hasChanges && !moc.save(&error){ 
      println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)") 
     } 
    } 
} 
} 

func saveBackgroundContext(){ 
    saveContext(self.defaultContext) 

    privateContext?.performBlock{ 
     var error : NSError? = nil 
     if let context = self.privateContext { 

      if context.hasChanges && !context.save(&error){ 
       println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)") 
      }else { 
       println("saved private context to disk") 
      } 
     } 
    } 
} 

Gdzie:

  • defaultContext ma concurrencyType .MainQueueConcurrencyType
  • privateContext ma concurrencyType .PrivateQueueConcurrencyType
Powiązane problemy