Компилятор LLVM 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.
person
Brad Larson
schedule
21.12.2011