2013-03-27 15 views
9

Witam każdego lata czytając StackOverflow, teraz zdecydowałem się dołączyć. Staram się rozwiązać ten problem:KVO addObserver do relacji jeden-do-wielu obiektów CoreData

Mam jednostkę "Depot", która ma dwa do wielu relacji "Osoby" i "Ciężarówki". Chcę zaobserwować, kiedy, biorąc pod uwagę obiekt "Depot", są zmiany (wstaw, usuń) w jednym z relacji (i zrozum, w którym).

Obecnie robię tak:

[mydepot addObserver:self forKeyPath:@"Trucks" options:NSKeyValueObservingOptionNew context:nil];

i

[mydepot addObserver:self forKeyPath:@"Persons" options:NSKeyValueObservingOptionNew context:nil];

ale za każdym razem coś się zmienia w jednym z dwóch powiązanych zbiorów, observeValueForKeyPath jest wywoływana dwukrotnie (raz dla każdego keypath).

Czy robię to źle? Patrząc na "zmianę" dict, (obserwując również z OptionOld) nie widać żadnych nieoczekiwanych zmian (kiedy zmieniam osoby, ciężarówki się nie zmieniają), ale powiadomienie wciąż jest wywoływane.

Dzięki Pietro

edit: wydaje się, że oba razy „zmiana” dict zawiera całą relacji w „nowej” polu. (oczywiście jednorazowo osoby i jednorazowe ciężarówki)

edit2: jak to się dzieje, nawet przy korzystaniu z prostych właściwości, czy może być powiązany z operacją składowania managedctx? tak jakby po zapisaniu cały obiekt został uznany za zmieniony.

Odpowiedz

3

Jeśli ustawisz wózki atomowe (something.trucks = newArray), otrzymasz powiadomienie o wartości zestawu. Zamiast tego użyj addObject/removeObject na tablicy zmiennych zwróconych przez [ something mutableArrayValueForKey:@"trucks" ].

Można również użyć/zaimplementować KVO generowane akcesorów insertObjectIntoTrucks:/countOfTrucks itp

Należy zapoznać się z dokumentacją KVO. W obszarze "Zindeksowane Zgodność z wieloma relacjami" i "Niezgodność z wieloma relacjami z wieloma osobami" here.

+1

+1 Zgadzam się. Zastanów się, jak zmodyfikować istniejący zbiór wartości, zamiast zastępować całą kolekcję inną kolekcją. – Caleb

+0

Dzięki, tak, ale Depot jest podklasą CoreData NSManagedObject, więc powinien już wdrożyć akcesory zgodne z KVO. I robię to, co mówisz, jako fakty dodam tylko nowy element do relacji, nigdy nie zastępując/ustawiając cały zestaw (relację). Dlatego nie mogę tego zrozumieć. Jakbym obserwował dla dwóch keypathów, na przykład "Trucks" i "sqmeters" (to nie jest relacja), jeśli "sqmeters" zostanie zmodyfikowany, wyzwalane są dwa powiadomienia (również jeden dla "ciężarówek" kpath) – Peterdeka

+0

Ścieżki kluczy mogą zależeć od siebie ... może to się dzieje? W przeciwnym razie będziesz musiał szukać gdzie indziej. – nielsbot

9

w kluczu wartość programową Obserwując Przewodnik mówi, że

Jeśli używasz danych Core, możesz zarejestrować się rodzica z aplikacją w centrum powiadomień jako obserwator jej kontekście zarządzanego obiektu. Rodzic powinien odpowiadać na odpowiednie powiadomienia o zmianach zamieszczane przez dzieci w sposób podobny do obserwowanego dla obserwacji wartości klucz-wartość.

To może oznaczać, że skutecznie zalecana praktyka nie jest w użyciu addObserver:forKeyPath:options:context:, ale zarejestrować się NSManagedObjectContextDidSaveNotification zamiast.

+0

Tak, to jest mój drugi wybór, ponieważ mam tylko jeden obiekt na raz, który chcę obserwować (ale wiele, które można zmodyfikować w tle), myślę, że jest to strata powiadomień, ponieważ otrzymuję powiadomienia o wszystkich zmianach obiektów i musi odfiltrować powiadomienia – Peterdeka

+1

@Peterdeka to wciąż najlepsza i poprawna odpowiedź. Powinieneś to zaakceptować. – Mundi

1

Pochodzę z tym samym problemem. I wciąż trzymam się tego problemu.

Ale jestem pewien, co jest powodem, że po raz pierwszy go nazwać to można zrobić coś jak [Depot addPerson:person] natomiast powodem po raz drugi go nazwać jest MOC zapisać działanie będzie umieścić NSManagedObjectContextDidSaveNotification powiadomienia który Let Your obserwator myśli, że inny zmienia się po prostu.

Co gorsza w moim problemie, to ze względu na obserwatora, utracę niektóre moje modyfikacje podstawowych danych.

To sprawia, że ​​czuję się tak głupia przez prawie dwa dni.

myślę użyć zarejestrować NSManagedObjectContextDidSaveNotification w odpowiedzi @Mundi „s

A jeśli ktoś ma lepszy sposób, proszę dać mi znać ASAP

0

Ciągle jakieś bufory wokół jak właściwościach NSManagedObject i konieczne do unieważnienia tych. Najpierw przyjrzałem się używaniu KVO i słuchaniu NSManagedObjectContextDidSaveNotification.

Najprostszym rozwiązaniem dla mnie było wdrożenie metod takich jak – [NSManagedObject didSave] i – [NSManagedObject didTurnIntoFault].

@interface BazClass() 
@property (nonatomic, strong) NSArray* sortedItems; // sorted items cache 
@end 

@implementation BazClass 

@dynamic items; // this is a to many relationship. i.e. NSOrderedSet 
@synthesize sortedItems; 

- (NSArray*)sortedItems 
{ 
    if (!_sortedItems) { 
     NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"foo" ascending:YES]; 
     _sortedItems = [self.items sortedArrayUsingDescriptors:@[sortDescriptor]]; 
    } 
    return _sortedItems; 
} 

// didSave and didTurnIntoFault will delete the sorted items cache 
- (void) didSave 
{ 
    self.sortedItems = nil; 
} 

-(void) didTurnIntoFault 
{ 
    self. sortedItems = nil; 
} 
Powiązane problemy