LLVM Compiler 3.0 вводить чотири нових класифікаторів власності: __strong
, __autoreleasing
, __unsafe_unretained
, і __weak
. Перші три доступні навіть за межами ARC, відповідно до специфікації .
Як вказує Джошуа, за замовчуванням усі вказівники мають на увазі, що вони знаходяться __strong
під ARC. Це означає, що коли об’єкт призначається цьому покажчику, він зберігається до тих пір, поки цей покажчик посилається на нього. Це добре для більшості речей, але це відкриває можливість для збереження циклів, як я описав у своїй відповіді тут . Наприклад, якщо у вас є об’єкт, що містить інший об’єкт як змінну екземпляра, але цей другий об’єкт має надійне посилання на перший як його делегат, ці два об’єкти ніколи не будуть звільнені.
Саме з цієї причини існують кваліфікатори __unsafe_unretained
та __weak
. Найчастіше їх використовують для делегатів, де ви визначаєте властивість для цього делегата за допомогою атрибута weak
або unsafe_unretained
( assign
ефективно unsafe_unretained
), а потім узгоджуєте це, позначаючи відповідну змінну екземпляра за допомогою __weak
або __unsafe_unretained
. Це означає, що змінна екземпляра делегата все одно буде вказувати назад на перший об'єкт, але це не призведе до того, що цей об'єкт буде збережено, тим самим порушуючи цикл збереження і дозволяючи звільнити обидва об'єкти.
Крім делегатів, це корисно, щоб розірвати будь-які інші цикли збереження, які можуть утворитися у вашому коді. Корисно, що інструмент «Витоки» тепер включає подання «Цикли», яке графічно відображає збережені цикли, виявлені у вашому додатку.
І те, __unsafe_unretained
і __weak
інше запобігає утриманню предметів, але дещо іншими способами. Адже __weak
вказівник на об'єкт перетвориться nil
на вивільнення об'єкта, на який він вказує, що є дуже безпечною поведінкою. Як випливає з назви, __unsafe_unretained
буде продовжувати вказувати на пам'ять, де знаходився об'єкт, навіть після того, як його було звільнено. Це може призвести до збоїв у роботі через доступ до цього звільненого об'єкта.
Чому ви коли-небудь використовували __unsafe_unretained
тоді? На жаль, __weak
підтримується лише для iOS 5.0 та Lion як цілі розгортання. Якщо ви хочете повернутися до iOS 4.0 та Snow Leopard, вам доведеться скористатися __unsafe_unretained
кваліфікатором або використати щось на зразок MAZeroingWeakRef Майка Еша .
__unsafe_unretained
може бути корисним для визначення масивів CNSString
констант тощо, наприкладNSString __unsafe_unretained *myStrings = { @"Foo", @"Bar", @"Baz", nil };