ARC - значення __unsafe_unretention?


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. Це означає, що змінна екземпляра делегата все одно буде вказувати назад на перший об'єкт, але це не призведе до того, що цей об'єкт буде збережено, тим самим порушуючи цикл збереження і дозволяючи звільнити обидва об'єкти.

Крім делегатів, це корисно, щоб розірвати будь-які інші цикли збереження, які можуть утворитися у вашому коді. Корисно, що інструмент «Витоки» тепер включає подання «Цикли», яке графічно відображає збережені цикли, виявлені у вашому додатку.

І те, __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може бути корисним для визначення масивів C NSStringконстант тощо, наприклад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це просто підказка компілятора, тоді як слабкий - ні. Більше інформації тут: stackoverflow.com/questions/11621028/…
Річард Дж. Росс III

4

__unsafe_unretainedє ідентичним тому, що сховище об’єкта за замовчуванням було до ARC. В ARC за замовчуванням тепер це __strongозначає, що у вас є посилання на нього, поки воно не виходить за межі сфери дії.


1

Ще одне зауваження щодо __unsafe_unretain: у моєму додатку на пристрої трапляються збої, а НЕ на симуляторі з iVars, оголошеним як __unsafe_unretention! Так, це була помилка в коді з міграції ARC, але вперше я помітив таку різницю між пристроєм та симулятором.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.