Слабый словарь в Objective-C - PullRequest
3 голосов
/ 09 апреля 2009

Мне интересно, возможно ли иметь что-то похожее на объект Dictionary ActionScript 3 со слабыми ключами в Objective-C. Я хочу иметь возможность «прикрепить» экземпляр класса к другим произвольным экземплярам.

Пример;

MetaData *meta = [MetaData metaDataForObject:someObject];
meta.whatever = foo;

И позже:

foo = [MetaData metaDataForObject:someObject].whatever;
[foo doStuff];

Сложность состоит в том, что после того, как возражение, на которое ссылается someObject, является dealloc'd, я хочу, чтобы объект, на который ссылается meta, был освобожден (и dealloc'd, при условии, что никакой клиентский код не сохранил его).

возможно? Я посмотрел на +[NSValue valueWithNonretainedObject:], но я не уверен, что это то, что я хочу, потому что там, когда я позже запрашиваю -[NSValue nonretainedObjectValue], кажется, что я получу указатель на мусор (как NSValue может обнулить указатель, когда объект был dealloc'd?).

Спасибо

Benjamin

Обновление 23 сентября 2011 года: Я считаю, что способ сделать это с помощью objc_setAssociatedObject и связанных функций. См. Objective-C Runtime Reference .

Ответы [ 2 ]

4 голосов
/ 10 апреля 2009

Звучит так, будто вы запрашиваете способность реагировать на освобождаемую переменную экземпляра со слабой ссылкой. Конечно, вы можете использовать атрибут __weak (с включенным GC), чтобы создать слабую ссылку, но нет встроенного механизма, который бы ловил, когда такой атрибут обнуляется после того, как его целью является GCed.

Если вы действительно этого хотите, лучше всего использовать тот же механизм, который использует Apple Key-Value Observing: метод swizzling. Сохраните глобальную таблицу (например, NSHashMap или NSMapTable), сопоставляющую объекты с соответствующими объектами метаданных, затем замените методы dealloc / finalize в классе объекта, к которому вы присоединяетесь, версиями, которые выглядят вверх соответствующий объект метаданных в таблице и отправить сообщение, чтобы разорвать его. (Вам также понадобится еще одна или две таблицы, которые отображают классы в их исходные dealloc / finalize методы.) JRSwizzle предоставляет хороший интерфейс для Swizzling.

Если вы хотите проявить особую фантазию, вместо перезаписи dealloc / finalize для всех объектов целевого класса, вы можете создать прокси-класс и переназначить указатель isa только для этого класса, например, что нет никакого снижения производительности при освобождении объектов, которые вы не смотрите. (КВО тоже это делает.)

1 голос
/ 09 апреля 2009

Вы ищете NSHashMap возможно? Обнуляет ссылки.

...