Если я правильно понимаю, вам нужен массив, который содержит слабые ссылки на свои элементы, в отличие от сильных ссылок?
Я не знаю, как это сделать с помощью чего-либо "встроенного-в "в какао.Единственный способ, которым я знаю об этом, - создать массив самостоятельно и иметь хранилище __weak id[]
.Это автоматически обнуляет место в массиве, когда объект освобождается.Если вы используете модель с повторным выпуском, вы можете использовать что-то вроде MAZeroingWeakRef
, чтобы получить то же поведение.
Это, безусловно, интересный вопрос, и я не знаю,более простого ответа.Я бы хотел оказаться неправым!
Ха, я люблю ошибаться!
Есть класс под названием NSPointerArray
, который выглядит так, как можетчто ты ищешь.Тем не менее, он доступен только на Mac, и это только автоматические нули, когда вы используете сборщик мусора.
Я буду продолжать думать об этом.Это интересная проблема!:)
Поэтому я продолжал думать об этом и придумал решение.Он использует две нетрадиционные вещи:
- Подкласс
NSMutableArray
(egads!) - Использование связанного объекта для определения освобождения объекта
ДляВо-первых, мне нужно было создать подкласс NSMutableArray
, чтобы я мог внедрить некоторую пользовательскую логику в addObject:
(и связанные методы).Я не хотел делать это через Swizzling, так как NSArray
и друзья являются кластером классов, а вхождение в / из кластеров чревато опасностью.Итак, подкласс.Это нормально, но мы потеряем некоторые удивительные функции, которые мы получаем от "чистых" NSArray
экземпляров, например , как они делают странные вещи, когда становятся большими .Ну что ж, такова жизнь.
Что касается второго бита, мне нужен был способ для любого произвольного объекта уведомить, что он собирается или только что завершил освобождение.Я подумал о том, чтобы динамически создать подкласс класса объекта, ввести свой собственный метод dealloc
/ finalize
, вызвать super
, а затем разбить isa
объекта, но это просто показалось слишком сумасшедшим.
Итак, я решил воспользоваться небольшой забавной штукой, которая называется связанные объекты.Это ивары, которые относятся к классам: они позволяют динамически добавлять и удалять переменные псевдоэкземпляра во время выполнения.У них также есть удивительный побочный эффект автоматической очистки с освобождением объекта.Поэтому я просто создал небольшой выбрасываемый объект, который отправляет уведомление, когда it освобождается, а затем присоединяет его к обычному объекту.Таким образом, когда обычный объект освобождается, выбрасываемый объект также будет иметь место, в результате чего будет опубликовано уведомление, которое я затем прослушиваю в подклассе NSMutableArray
.Уведомление содержит (устаревший) указатель на объект, который находится в процессе уничтожения, но, поскольку меня интересует только указатель , а не объект , все в порядке.
Результатом всего этого является то, что вы можете сделать:
DDAutozeroingArray *array = [DDAutozeroingArray array];
NSObject *o = [[NSObject alloc] init];
[array addObject:o];
NSLog(@"%ld", [array count]); //logs "1"
[o release];
NSLog(@"%ld", [array count]); //logs "0"
Источник находится на github, и он должен (теоретически) работать так же хорошо на iOS, как Mac OS X (независимо от того,Режим GC): https://github.com/davedelong/Demos
Приветствия!
... и я просто подумал, как сделать это без пользовательского подкласса, но я устал и выложузавтра обновленный ответ.
на следующее утро ...
Я только что обновил проект на Github с категорией NSMutableArray
, которая позволяет вамсоздать истинное значение NSMutableArray
, которое автоматически обнуляет свои объекты по мере их освобождения.Трюк состоял в том, чтобы создать CFMutableArrayRef
с пользовательским retain
обратным вызовом, который устанавливает правильное наблюдение, а затем просто навести это CFMutableArrayRef
на NSMutableArray
и использовать это (ах, магия Toll-Free Bridging).
Это означает, что теперь вы можете:
NSMutableArray *array = [NSMutableArray autozeroingArray];
Я добавил typedef
, чтобы определить их как NSAutozeroingMutableArray
, просто чтобы четко дать понять, что, хотя это NSMutableArray
, он не retain
его объектов, как обычный NSMutableArray
. Однако, поскольку это просто typedef
, а не подкласс, вы можете использовать их взаимозаменяемо.