ARC - значение __unsafe_unrehibited?

80

Просто хочу убедиться, что я правильно понял:

  1. Нужны ли мне __unsafe_unretainобъекты, которыми я не владею?
  2. Если объект - __unsafe_unretainedнужно ли мне использовать assignв @property? Означает ли это, что объект не сохраняется, а просто ссылается на объект, который я назначаю?
  3. Когда я захочу использовать его, кроме делегатов?
  4. Это вещь ARC или она использовалась раньше?
Шаннога
источник

Ответы:

192

LLVM Compiler 3.0 вводит четыре новых классификаторов собственности: __strong, __autoreleasing, __unsafe_unretained, и __weak. Первые три доступны даже за пределами ARC, согласно спецификации .

Как указывает Джошуа, по умолчанию подразумевается, что все указатели находятся __strongпод ARC. Это означает, что когда объект назначается этому указателю, он сохраняется до тех пор, пока этот указатель ссылается на него. Это нормально для большинства вещей, но открывает возможность для сохранения циклов, как я описываю в своем ответе здесь . Например, если у вас есть объект, который содержит другой объект в качестве переменной экземпляра, но этот второй объект имеет сильную обратную связь с первым в качестве своего делегата, эти два объекта никогда не будут освобождены.

Именно по этой причине существуют квалификаторы __unsafe_unretainedи __weak. Чаще всего они используются для делегатов, где вы определяете свойство для этого делегата с помощью атрибута weakили unsafe_unretained( assignфактически unsafe_unretained), а затем сопоставляете его, отмечая соответствующую переменную экземпляра с помощью __weakили __unsafe_unretained. Это означает, что переменная экземпляра делегата по-прежнему будет указывать на первый объект, но это не приведет к тому, что этот объект будет сохранен, тем самым прервав цикл сохранения и позволив освободить оба объекта.

Помимо делегатов, это полезно для разрыва любых других циклов сохранения, которые могут образоваться в вашем коде. К счастью, инструмент Leaks теперь включает представление Cycles, в котором графически отображаются циклы сохранения, обнаруженные в вашем приложении.

Оба __unsafe_unretainedи __weakпредотвращают задержку предметов, но несколько разными способами. Ведь __weakуказатель на объект будет преобразован в nilпри освобождении объекта, на который он указывает, что является очень безопасным поведением. Как следует из названия, __unsafe_unretainedбудет продолжать указывать на память, в которой находился объект, даже после того, как он был освобожден. Это может привести к сбоям из-за доступа к этому освобожденному объекту.

Зачем __unsafe_unretainedтогда использовать ? К сожалению, в __weakкачестве целей развертывания поддерживается только iOS 5.0 и Lion. Если вы хотите вернуться к iOS 4.0 и Snow Leopard, вы должны использовать __unsafe_unretainedквалификатор или использовать что-то вроде MAZeroingWeakRef Майка Эша .

Брэд Ларсон
источник
2
И, конечно же, __unsafe_unretainedможет быть полезно для определения массивов NSStringконстант C и т.п., напримерNSString __unsafe_unretained *myStrings = { @"Foo", @"Bar", @"Baz", nil };
jlehr
2
@shannoga - Нет, вам нужно вручную указать __weakв качестве квалификатора, чтобы он использовал такие указатели. Вы все еще можете использовать __unsafe_unretainedс целью только 5.0, и она не будет вести себя как __weak. Если вам нужно что-то, что будет переключаться между двумя режимами в зависимости от того, поддерживает ли это ваша цель, вы можете использовать определение для конкретного компилятора, как я предлагаю здесь: stackoverflow.com/a/8594878/19679
Брэд Ларсон
4
@jlehr - неверный NSString *myStrings = { @"Foo", @"Bar" };синтаксис Objective-C; @"Foo"имеет тип NSString*сам по себе. Возможно, вы имели в виду NSString *myStrings[] = { @"Foo", @"Bar" };, но в таком случае я не очень понимаю, как это __unsafe_unretainedбыло бы особенно полезно.
Quuxplusone
2
@Quuxplusone Правильно по обоим пунктам - я смешивал массивы C со структурами. Я должен был сказать, что __unsafe_unretainedмогут быть полезны члены структур C, которые указывают на константы NSString, напримерstruct foo { __unsafe_unretained NSString * const s; int x; };
jlehr
1
Также имеет значение для Class. См .: stackoverflow.com/a/14245894/392847
Квинтин Уиллисон,
4
  1. Нет, вы также можете использовать weakдля объектов, которые вам не принадлежат.
  2. Нет, вы также можете использовать unsafe_unretainedв собственности.
  3. Насколько я понимаю, unsafe_unretainedэлементы такие же weak, без дополнительной безопасности, связанной с их удалением, когда элемент, на который они указывают, освобождается (и накладные расходы, связанные с этим).
  4. Это полностью относится к ARC.
Сергей Калиниченко
источник
На самом деле, как ни странно, unsafe_unretainediVars, когда они установлены во время выполнения, ведут себя так же, как и strongдругие, что заставляет меня думать, что unsafe_unretainedэто просто подсказка компилятора, а weak - нет. Дополнительная информация здесь: stackoverflow.com/questions/11621028/…
Ричард Дж. Росс III
4

__unsafe_unretainedидентично тому, что хранилище объекта по умолчанию было до ARC. С ARC значение по умолчанию теперь __strongозначает, что у вас есть ссылка на него, пока ваша ссылка не выйдет за рамки.

Джошуа Вайнберг
источник
1

Еще одно наблюдение о __unsafe_unrehibited: у меня возникают сбои в моем приложении на устройстве, а НЕ на симуляторе с iVars, объявленным как __unsafe_unrehibited! Да, это была ошибка в коде миграции ARC, но я впервые заметил такую ​​разницу между устройством и симулятором.

Герд
источник