Владение указателем ARC Objective C против переполнения стека

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

- (void) doSomeStuff {
MyBusinessObject* obj = [[MyBusinessObject alloc] init];
[obj setFoo:@"bar"];
[dataManager takeObj:obj withKey:@"abc" andKey:@"def"];
}

а затем в реализации takeObj Я хочу сохранить два разных словаря …

- (void) takeObj:(MyBusinessObject*)obj withKey:(NSString*)key1 andKey:(NSString*)key2 {
[primaryDict setObject:obj forKey:key1];
[secondaryDict setObject:obj forKey:key2];
}

Теперь я хочу владеть obj быть переданным моему менеджеру данных и иметь primaryDict держать сильные ссылки и secondaryDict держать слабые ссылки. Вот как я бы сделал это в C ++:

map<string, unique_ptr<MyBusinessObject>> primaryDict;
map<string, MyBusinessObject*> secondaryDict;

takeObj функция будет принимать unique_ptr<MyBusinessObject> это будет передано с std::move, Это будет затем перенесено снова в primaryDict и слабая ссылка будет добавлена ​​с необработанным указателем в secondaryDict,

Мой вопрос — как правильно сказать системе ARC Objective-C для управления моими ссылками таким образом?

1

Решение

Используйте NSMapTable, а не NSDictionary для хранения ваших слабых ссылок. Проверить документация, особенно раздел о NSMapTableOptions.

Вы можете создать таблицу карт с тем же поведением, что и у NSDictionary, но со слабыми ссылками на значения, инициализируя с помощью:

[NSMapTable mapTableWithKeyOptions:NSMapTableCopyIn valueOptions:NSMapTableWeakMemory]

Это Obj-C эквивалент:

std::map<std::string, std::weak_ptr<MyBusinessObject>>

Значения не будут сохранены, и ссылка будет автоматически установлена ​​равной нулю, когда объект освобождается. Однако запись таблицы не удаляется, поэтому вы можете проверить наличие записей со значениями nil и время от времени удалять их, в зависимости от того, сколько разных ключей вы ожидаете.

Обратите внимание, что обычно нет причин делать это, если вам не нужны циклические ссылки или не реализовано что-то вроде кеша. Сильная ссылка похожа на std::shared_ptr в C ++, и соглашение в Objective-C состоит в том, чтобы делиться ссылками на один объект, а не копировать / перемещать с одним владельцем (вы закончите борьбу против языка / фреймворков, если попытаетесь сделать это по-другому).

1

Другие решения

Итак, экземпляр с -takeObj:... метод владеет obj после прохождения? Почему это важно, если это происходит с двумя сильными ссылками, а не с одной? Короче говоря, просто используйте NSMutableDictionary и пусть оба словаря имеют сильные ссылки на obj, Для этого нет заметного снижения производительности, а в базовых коллекциях нет встроенной поддержки обнуления слабых ссылок, поэтому, если вы это подразумеваете под «слабым», вы все равно останетесь сами по себе.

0

По вопросам рекламы [email protected]