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 Майка Эша .
__unsafe_unretained
может быть полезно для определения массивовNSString
констант C и т.п., напримерNSString __unsafe_unretained *myStrings = { @"Foo", @"Bar", @"Baz", nil };
__weak
в качестве квалификатора, чтобы он использовал такие указатели. Вы все еще можете использовать__unsafe_unretained
с целью только 5.0, и она не будет вести себя как__weak
. Если вам нужно что-то, что будет переключаться между двумя режимами в зависимости от того, поддерживает ли это ваша цель, вы можете использовать определение для конкретного компилятора, как я предлагаю здесь: stackoverflow.com/a/8594878/19679NSString *myStrings = { @"Foo", @"Bar" };
синтаксис Objective-C;@"Foo"
имеет типNSString*
сам по себе. Возможно, вы имели в видуNSString *myStrings[] = { @"Foo", @"Bar" };
, но в таком случае я не очень понимаю, как это__unsafe_unretained
было бы особенно полезно.__unsafe_unretained
могут быть полезны члены структур C, которые указывают на константы NSString, напримерstruct foo { __unsafe_unretained NSString * const s; int x; };
Class
. См .: stackoverflow.com/a/14245894/392847weak
для объектов, которые вам не принадлежат.unsafe_unretained
в собственности.unsafe_unretained
элементы такие жеweak
, без дополнительной безопасности, связанной с их удалением, когда элемент, на который они указывают, освобождается (и накладные расходы, связанные с этим).источник
unsafe_unretained
iVars, когда они установлены во время выполнения, ведут себя так же, как иstrong
другие, что заставляет меня думать, чтоunsafe_unretained
это просто подсказка компилятора, а weak - нет. Дополнительная информация здесь: stackoverflow.com/questions/11621028/…__unsafe_unretained
идентично тому, что хранилище объекта по умолчанию было до ARC. С ARC значение по умолчанию теперь__strong
означает, что у вас есть ссылка на него, пока ваша ссылка не выйдет за рамки.источник
Еще одно наблюдение о __unsafe_unrehibited: у меня возникают сбои в моем приложении на устройстве, а НЕ на симуляторе с iVars, объявленным как __unsafe_unrehibited! Да, это была ошибка в коде миграции ARC, но я впервые заметил такую разницу между устройством и симулятором.
источник