2012-03-09 9 views
5

Spodziewam się (mam nadzieję, że), że to będzie głupie pytanie, ale po tym, jak przez wiele godzin borykam się z tym problemem, potrzebuję trochę wglądu.Powielanie encji, gdy zmiana dokonana przez dziecko ManagedObjectContext jest popychana (zapisywana) do rodzica

Moja aplikacja iOS 5.1 korzysta z zagnieżdżonych MOC-ów, posiadających MOC-dziecko z PrivateQueueConcurrency, nazywa je MOC-Child, którego rodzicem jest MainQueueConcurrency MOC, nazwij go MOC-Parent. MOC-Parent popiera widok tabeli, który wyświetla jego encje.

MOC-Child jest używany przez analizator składni, który działa asynchronicznie w wątku innym niż główny, w celu utworzenia nowych encji odpowiadających opisom encji XML przeanalizowanych z połączenia URL, a następnie przekazania nowych elementów do MOC-a Rodzic, poprzez zapis na MOC-Child, który wyświetla je w widoku tabeli. Działa to doskonale:

1) Parser creates entity in MOC-Child 
2) Parser saves MOC-Child 
3) New entity is added to MOC-Parent 
4) New entity is displayed in MOC-Parent's table view 

Jednak opis danego podmiotu w tej paszy może zmieniać się w czasie, tak aby jednostka opisuje musi być modyfikowany w aplikacji, a jego komórka w widoku tabeli zaktualizowane. Tak więc dla każdego opisu obiektu w kanale, parser próbuje pobrać encję (jeśli jest) w MOC-Child, która ma ten sam identyfikator, co opisana encja, i jeśli istnieje jedna porównuje wartości istniejącej encji z wartościami opisowymi do zobacz, czy coś się zmieniło. Kiedy parser wykryje w ten sposób, że obiekt został zmodyfikowany, aktualizuje wartości istniejącej jednostki w MOC-Child z nowymi wartościami w opisie, a następnie zapisuje MOC-Child, aby przesunąć zmiany do MOC-Parent.

Tutaj wszystko idzie nie tak. Myślałem, że zmiany dokonane w pobranej jednostce w MOC-Child, kiedy zostaną zepchnięte do rodzica poprzez zapisanie go, po prostu "pojawiają się" w "tej samej" jednostce w MOC-Parent. Jednak widzę, że zmieniony byt z MOC-Child został dodany do MOC-Parent, , jakby był całkowicie oddzielnym i nowym bytem; z takim skutkiem, że MOC-Parent, a tym samym napędza go zobaczyć stół, kończy się dwa jednostek dla każdej zmodyfikowanej jednostki:

1) Parser modifies existing entity in MOC-Child 
2) Parser saves MOC-Child 
3) Modified entity is _added to_ MOC-Parent 
4) Entity is displayed _twice_ in MOC-Parent's table view 

Co daje? Co muszę zrobić, aby zmienić wartości istniejącej jednostki w MOC-Parent, jeśli nie mogę tego zrobić w MOC-Child? A jeśli mógłbym to zrobić w MOC-Child, co jeszcze muszę zrobić, oprócz zapisania MOC-Child, aby wprowadzić zmiany w MOC-Parent bez dodawania encji po raz drugi?

Z góry dziękujemy za wszelką pomoc lub wgląd, jaki możesz zaoferować!

Carl

P.S. Kilka wyjaśnień. Kiedy mówię, że zmieniona jednostka jest dodana do MOC-Parent, mam na myśli to, że NSFetchedResultsController monitorujący MOC-Parent wydaje typ zmiany NSFetchedResultsChangeInsert (nie typu zmiany NSFetchedResultsChangeUpdate) dla zmienionego obiektu, mimo że " ten sam "podmiot jest już obecny w MOC-Parent.

Ponadto, gdy mówię "ten sam" podmiot, mam na myśli podmiot w MOC-Parent, który ma ten sam identyfikator podany w opisie (w tym przypadku NSString) jako podmiot, który został zmieniony w MOC-child (nie koniecznie ten sam objectID, w rzeczywistości najwyraźniej mający inny objectId).

+0

Mam ten sam problem. Mam NSFetchedResultsController dołączony do zagnieżdżonych kontekstów z UIManagedDocument. Właśnie ładuję z serwera na rodzica w tle, a następnie pokazuję go od dziecka na pierwszym planie. Ale nie działa właściwie bez względu na wszystko. Jeśli zamknę aplikację i ponownie ją otworzę, ładuje się ona doskonale z pamięci. Dziwny. –

Odpowiedz

1

Wyobrażam sobie, że skoro jest to tak stare pytanie, to już nie jest problem. Ale ponieważ ostatnio zmagałem się z podobną sytuacją, pomyślałem, że zaoferuję swoje rozwiązanie.

Pobieram tablicę tysięcy obiektów (które są powiązane przez jeden lub więcej kodów kreskowych) z plikiem XML, który następnie analizuję i zapisuję partiami kontekstu tła za pomocą podklasy NSOperation. Kontekst dysku (połączony z magazynem trwałym) nasłuchuje dla NSManagedObjectContextDidSaveNotification, w którym to momencie również zapisuje (pamiętaj, aby zrobić to w bloku).

[self.diskManagedObjectContext performBlockAndWait:^{ 
    NSError *error; 
    if (![self.diskManagedObjectContext save:&error]) { 
     NSLog(@"error saving to disk: %@",error); 
    } 
}]; 

Najtrudniejsze jest to, że każdy z tych obiektów kody kreskowe może być skanowane (w kontekście UI) zanim plik XML został w pełni analizowany i informacje załadowane do bazy danych. I mam widok tabeli wspierany przez NSFetchedResultsController, który wyświetla zeskanowane obiekty, które pokazują "nieznany" w swoich tytułach, dopóki dane nie zostaną pobrane z ładowania w tle. Podobnie jak w przypadku Carla, obiekty te muszą zostać zaktualizowane, gdy kontekst tła zostanie zapisany.

Do obsługi tego używam systemu z trzema kontekstami podobnego do tego w this question, z kontekstem UI i kontekstem tła, z których oba są elementami potomnymi głównego kontekstu dysku (który jest powiązany z magazynem trwałym). Tak więc podczas analizowania XML uruchamiam zapytanie o kody kreskowe obiektu w kontekście kontekstowym (które również pobiera z kontekstu dysku nadrzędnego), aby sprawdzić, czy obiekt został już utworzony z tym kodem kreskowym. Jeśli tak, to tylko aktualizuję informacje, ponownie zapisuję, resetuję kontekst dysku i wywołuję refreshObject: mergeChanges: z kontekstu UI, aby wyciągnąć te zmiany z kontekstu dysku. Pomoże to odświeżyć tabelę bez tworzenia duplikatów.

Pierwotnie wypróbowałem to używając tylko dwóch kontekstów, kontekstu tła i kontekstu UI, ale chociaż nigdy nie skończyłem tworzyć duplikatów obiektów, naprawdę dobrze mi się powiesił wątek UI.

Domyślam się, że ważne pytanie brzmi: W jaki sposób modyfikujesz istniejący byt? I nie zapomnij zresetować.

+0

Właściwie to jeszcze nie rozwiązałem tego problemu, więc jest to wciąż aktualne, przynajmniej dla mnie. (Właśnie punted w sprawie, wykonując parsowanie jako asynchroniczne zadanie w głównym wątku - oczywiście nie jest idealny!) Kiedy dostanę szansę, przerobię mój schemat analizowania, aby wypróbować twoje rozwiązanie. W międzyczasie, dzięki za informację! –

+0

Pewnie. Jeśli chcesz uzyskać więcej informacji podczas wypróbowania, daj mi znać, a podam nieco bardziej szczegółowe wyjaśnienie. – enjayem

Powiązane problemy