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 };