Подтвердить что ты не робот

NSManagedObject как ключ NSDictionary?

В моем приложении у меня есть NSDictionary, ключи которого должны быть экземплярами подкласса NSManagedObject.

Проблема, однако, заключается в том, что NSManagedObject не реализует протокол NSCopying, что означает, что никакие объекты/экземпляры Core Data NSManagedObject не могут использоваться в качестве клавиш словаря, даже если метод -[hash] отлично работает для их.

Я должен был делать?

4b9b3361

Ответ 1

Существует четыре варианта:

  • Вместо этого используйте другой объект в качестве словарного ключа и найдите его. [object objectID] или +[NSValue valueWithNonretainedObject:] кажутся наиболее очевидными
  • Используйте CFDictionaryCreateMutable() для создания словаря с сохраненными ключами вместо скопированного вместо него, а затем вызывайте CFDictionarySetValue() для хранения объектов
  • В OS X или iOS6 +, [NSMapTable mapTableWithStrongToStrongObjects] вы получаете чисто Objective-C эквивалент CFMutableDictionary
  • Внедрите NSCopying для вашего подкласса управляемого объекта, чтобы он возвращал self (с подсчетом ссылок, если вы не используете ARC)

Примечания

+valueWithNonretainedObject: довольно опасен, так как его можно оставить с висящим указателем; вероятно, лучше всего избегать.

Сохранение идентификаторов объектов прекрасно, кроме того, что новые объекты начинают жизнь с временным идентификатором. Затем этот идентификатор изменяется на постоянный, когда контекст сохраняется на диск (или вызывается -obtainPermanentIDsForObjects:…). Ваш код сопоставления должен быть достаточно умным, чтобы справиться с этим, если он не может гарантировать, что все входящие объекты уже имеют постоянный идентификатор.

Реализация NSCopying, как это чувствует себя немного icky, но должно работать нормально. Как это бывает, это именно подход NSURLSessionTask принимает, я полагаю, что для удобства словаря.

До OS X 10.8 Mountain Lion раньше можно было создать обычный NSMutableDictionary, а затем вызвать CFDictionarySetValue() для него. Однако это не так. теперь в новых словарях есть надлежащие обратные вызовы копирования, указанные на уровне CF, а не только как функция NSMutableDictionary.

Ответ 2

Не удалось создать класс-оболочку, содержащий ссылку на экземпляр NSManagedObject, который вы хотите использовать в качестве словарного ключа? Затем вы можете сделать этот класс-оболочку реализацией NSCopying вместе с хеш-методом (возможно, просто вызовом метода хэш файла NSManagedObject) и использовать эту оболочку в качестве словарного ключа.

Ответ 3

Я предлагаю использовать [[[myManagedObject objectID] URIRepresentation] absoluteString] как ваш ключ.

Ответ 4

У меня была аналогичная проблема, в которой мне нужно было объединить несколько объектов с дополнительными данными для каждого и изначально попытался:

@{entity1:data1, @entity2:data2, @entity3:data3}

это не работало по причине выше (NSCopying), поэтому я сделал:

@[
   @{@"entity":entity1, @"data":data1},
   @{@"entity":entity2, @"data":data2},
   @{@"entity":entity3, @"data":data3}
]

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