бесхозные vs. слабые. Почему мы должны отдавать предпочтение бесхозным?

Как Apple сказала в «Swift Programming Language», кажется, мы должны предпочесть unowned, а не weak, когда это возможно:

Если захваченная ссылка никогда не станет нулевой, ее всегда следует захватывать как бесхозную ссылку, а не как слабую.

Из раздела «Слабые и неизвестные ссылки» на этом страница

Я знал разницу между этими двумя. Но мне любопытно, есть ли веские причины предпочесть unowned, а не weak? Я думаю, что weak намного безопаснее, и мы всегда можем просто написать [weak obj] и дополнительную проверку привязки, не задумываясь о возможности существования obj.

Это связано с некоторыми соображениями производительности или с чем-то, что я упустил? Или можно все время использовать weak вместо unowned?


person onevcat    schedule 19.08.2014    source источник


Ответы (2)


Слабые ссылки автоматически устанавливаются на nil, как только объект, на который они указывают, освобождается. Чтобы это было возможно в Swift, они должны быть объявлены как var и необязательны:

class SomeOtherClass {
    weak var weakProperty: SomeClass?
}

Это нормально, если weakProperty может стать nil, пока экземпляр SomeOtherClass еще жив, и мы хотим проверить это перед его использованием (делегаты - один из таких примеров). Но что, если какая-то ссылка по логике никогда не должна быть nil, и мы по-прежнему хотим предотвратить цикл сохранения? В Objective-C любая ссылка на объект может быть nil (а обмен сообщениями nil всегда завершается сбоем), поэтому нет дилеммы, мы всегда используем weak. Но в Swift вообще нет ссылок с нулевым значением. Мы используем необязательные параметры для чего-то, что может семантически не иметь значения. Но мы не должны быть принуждены использовать опции для чего-то, что всегда должно иметь значение, просто чтобы иметь возможность разорвать цикл сохранения. Такая практика противоречила бы предполагаемой семантике опционалов.

Вот где приходит unowned. Он бывает двух видов - unowned(safe) и unowned(unsafe). Последнее опасно и эквивалентно assign и unsafe_unretained из Objective-C. Но первый, который используется по умолчанию (по крайней мере, во время отладки; не уверен, оптимизируют ли они его до unowned(unsafe) в сборках выпуска), надежно приведет к сбою вашего приложения, если указанный объект будет преждевременно освобожден. Конечно, ваше приложение выйдет из строя, если что-то пойдет не так, но отладить это намного проще, чем потерпеть неудачу незаметно. Он должен терпеть неудачу только тогда, когда вы действительно этого хотите (в этом случае вы должны использовать weak)

person Ivica M.    schedule 19.08.2014
comment
Это имеет смысл. Спасибо за Ваш ответ. - person onevcat; 20.08.2014

[атрибуты свойства Objective-C]

ARC - Automatic Reference Counting - это механизм управления памятью, применимый для reference типа [About] . Объект освобождается только тогда, когда на нем 0 ссылок.

Strong reference - установлен по умолчанию, и этот тип безопасно использовать в линейных отношениях (нет цикла)

Retain cycle - это ситуация, когда каждый объект имеет сильную ссылку друг на друга

Разбейте Retain cycle: weak и unowned. Оба они не увеличивают счетчик удержания объекта на +1 и имеют следующие отличия

Weak reference - Когда объект ссылки освобожден (nil), ARC также устанавливает weak ссылку на nil. Вот почему ссылка weak является переменной var (не может быть константой let) [var vs let] < / a> и поэтому это optional

weak var delegate: <Type>?

ОБЩИЕ

unowned - Когда объект ссылки освобожден (nil), unowned не становится nil, потому что ARC не устанавливает его. Вот почему unowned ссылка является необязательной.

без владельца (по умолчанию)

safe unowned - использует runtime safety check для выдачи исключения, если unowned ссылка была освобождена.

Fatal error: Attempted to read an unowned reference but object 0x7fa5dad3f0f0 was already deallocated

unowned (небезопасно)

unowned(unsafe) работает с UnsafePointer, который может создать dangling pointer. __unsafe_unretained из Objective-C. Это своего рода прямой доступ к памяти, который ARC не обрабатывается. Это может вызвать неожиданное поведение, а не просто сбой. У него лучшая производительность

EXC_BAD_ACCESS

[EXC_BAD_ACCESS]
[Пример закрытия]

person yoAlex5    schedule 03.04.2020