Основные данные: Наблюдение за изменениями в связанных объектах - PullRequest
6 голосов
/ 30 мая 2011

У меня есть образец модели управляемого объекта, изображенный на рисунке ниже. Я хотел бы, чтобы это происходило так: когда объект, который является значением для отношения валюты в объекте Bar, изменяется, автоматически устанавливать этот же объект в качестве отношения валюты во всех Foo, которые связаны с этим Bar через отношения foos.

enter image description here

Правильно ли я понимаю, что это можно сделать через КВО? Я хотел начать с добавления этого в Foo.m:

+ (NSSet *)keyPathsForValuesAffectingCurrency {
    return [NSSet setWithObject:@"bar.currency"];
}

но я не могу понять, правильно ли это или как я буду действовать дальше. Спасибо за любой совет.

Ответы [ 2 ]

3 голосов
/ 18 июля 2013

То, чего вы хотите достичь, безусловно, возможно, и КВО может позаботиться об этом.Вам просто нужно реализовать несколько вещей.

1.Зарегистрируйтесь для наблюдения за ключом, влияющим на вашу собственность

Вы можете добавить свой объект в качестве наблюдателя, когда ваш объект просыпается.

- (void) awakeFromInsert {
  [super awakeFromInsert];
  [self addObserver:self forKeyPath:@"bar.currency" options:NSKeyValueObservingOptionNew context:nil];
}

// Repeat for awakeFromFetch

Обратите внимание, что это работает в этом случае, так как этоотношение один к одному.

2.Принять меры при срабатывании уведомления

Обновите значение currency при срабатывании уведомления для bar.currency

- (void) observeValueForKeyPath:(NSString *)keyPath
                       ofObject:(id)object
                         change:(NSDictionary *)change
                        context:(void *)context
{
  if( [keyPath isEqualToString:@"bar.currency"] ) {
    [self setValue:[self valueForKeyPath:@"bar.currency"] forKey:@"currency"];
  }

  // The rest of your KVO logic ...
}

Альтернативный подход

Как вы указалиэто также может быть сделано путем реализации зависимых ключей

+ (NSSet *)keyPathsForValuesAffectingCurrency {
  return [NSSet setWithObject:@"bar.currency"];
}

В этом случае вместо этого вам придется соблюдать @"currency".В вашем методе observeValue... вы должны проверить этот ключ.Наконец, вам нужно установить значение, используя setPrimitiveValue:forKey вместо setValue:forKey:.Это потому, что последний вызовет новое уведомление и приведет к бесконечному циклу.

1 голос
/ 31 мая 2011

Есть несколько возможных решений:

  1. Переопределить установщик setCurrency в Bar, чтобы также изменить валюту в Foo
  2. Используйте KVO ( ADC ), чтобы обновить отношение Foo, если валюта бара изменяется. Будьте осторожны с KVO в сочетании с Базовыми данными (обработка ошибок и отказов довольно сложны)
  3. Пересмотрите свою модель данных, если это лучшее решение для вашей проблемы
...