Допустим, у меня есть класс высокого уровня, который создает экземпляр объекта и затем передает его классу более низкого уровня:
- (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 для управления моими ссылками таким образом?
Используйте 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 состоит в том, чтобы делиться ссылками на один объект, а не копировать / перемещать с одним владельцем (вы закончите борьбу против языка / фреймворков, если попытаетесь сделать это по-другому).
Итак, экземпляр с -takeObj:...
метод владеет obj
после прохождения? Почему это важно, если это происходит с двумя сильными ссылками, а не с одной? Короче говоря, просто используйте NSMutableDictionary
и пусть оба словаря имеют сильные ссылки на obj
, Для этого нет заметного снижения производительности, а в базовых коллекциях нет встроенной поддержки обнуления слабых ссылок, поэтому, если вы это подразумеваете под «слабым», вы все равно останетесь сами по себе.