Как сделать идеальный КВО для NSManagedObject? - PullRequest
7 голосов
/ 30 сентября 2011

Идеальное КВО здесь состоит из двух частей: правильно добавить наблюдателя и правильно удалить наблюдателя.

История:

  1. Я использую один UITableViewCell (ячейка) для отображения одного NSManagedObject (объект).
  2. Каждый объект имеет некоторые динамические свойства, которые необходимо наблюдать по его ячейке.
  3. Не все объекты имеют одинаковый набор наблюдаемых свойств. Я добавляю ключевые наблюдатели пути выборочно, как это:

    if (object.thumbnail_pic_url) [объект addObserver: ячейка forKeyPath: @ «thumbnail_picture» опции: 0 контекст: NULL];

  4. Объект может быть удален. Я должен удалить наблюдателей, когда объект удален. База данных очень большая и сложная, поэтому я определенно не хочу регистрировать все ячейки для получения уведомлений moc, таких как NSManagedObjectContextObjectsDidChangeNotification. Но я могу согласиться добавить ячейку ivar в объект, если потребуется, даже если это повторяет хороший шаблон проектирования Modle-View-Controller.

Проблема: как правильно удалить наблюдатель (ячейку) для всех зарегистрированных путей ключа из объекта при его удалении?

На самом деле, это большая проблема, которую можно разделить на две небольшие проблемы:

  1. Где лучше всего разместить код удаления наблюдателя?
  2. Как определить, какие ключевые пути отменить регистрацию? Я не могу запросить его свойства после того, как объект удален - это приведет к невыполнимым ошибкам, поэтому я не могу написать такой код:

    if (object.thumbnail_pic_url) [object removeObserver: ячейка forKeyPath: @ "thumbnail_picture"];

и я не могу ни слепо удалить наблюдателя для незарегистрированного пути ключа - исключения (невозможно удалить наблюдателя для ключевого пути "thumbnail_picture", поскольку он не зарегистрирован как наблюдатель.) Будут выброшены.

Ответы [ 3 ]

3 голосов
/ 01 октября 2011

an0,

Существует метод NSManagedObject только для удаления временных функций: -prepareForDeletion.

В его документации утверждается: «Вы можете реализовать этот метод для выполнения любых операций, требуемых до удаления объекта, таких как пользовательское распространение до разрушения связей или реконфигурирование объектов с использованием наблюдения значения ключа».

Вы также можете посмотреть с помощью: -willTurnIntoFault и -didTurnIntoFault.Но я думаю, что вы будете счастливее, используя -prepareForDeletion.

Andrew

PS Этот метод описан в справочнике по классам.С уважением предлагаю вам сэкономить время, читая документацию.

0 голосов
/ 28 января 2019

Я считаю, что ошибка в шаге 1. Ячейки должны быть спроектированы так, чтобы отображать разные объекты.Ячейки - это просто представления с метками, которые могут показывать что угодно.Таблицы оптимизированы для повторного использования одних и тех же ячеек для разных объектов данных.В вашем VC создайте методы configureCellWithEvent, configureCellWithVenue и т. Д., Затем вы можете удалить из очереди ячейку универсального идентификатора и передать ее этим методам.Тогда у вас, вероятно, даже не возникнет вопроса о том, когда добавлять наблюдателей удаления, поскольку в ячейках не должно быть наблюдателей объектов.

0 голосов
/ 04 апреля 2014

Основная проблема реализации KVO заключается в том, что вы не знаете, когда объект удаляется, по крайней мере, за пределами подкласса NSManagedObject. Что вы действительно можете сделать, так это создать общий делегат для подкласса NSManagedObject и переопределить его didChangeValueForKey: метод

  // DataObservingManagedObject.h

  #import <Foundation/Foundation.h>
  #import <MMRecord/MMRecord.h>

  @protocol DataObservingDelegate <NSObject>

  -(void)valueChangedForKey:(NSString*)key andValue:(id)value;
  @end

  @interface DataObservingManagedObject : NSManagedObject

  @property(nonatomic,weak)id<UserStatusDelegate> changeDelegate;

  @end

  //DateObservingManagedObject.m

  #import "DateObservingManagedObject.h"

  @implementation DateObservingManagedObject

  @synthesize changeDelegate=_changeDelegate;


  -(void)didChangeValueForKey:(NSString *)key{
    [self.changeDelegate valueChangedForKey:key andValue:[self valueForKey:key]];
  }

  @end
...