Непризнанный или слабый Почему мы должны отдавать предпочтение бесхозным?
Как сказал Apple в "The Swift Programming Language", похоже, нам следует отдать предпочтение unowned
чем weak
когда возможно:
Если захваченная ссылка никогда не станет равной нулю, она должна всегда учитываться как не имеющая ссылки, а не как слабая ссылка.
Из раздела "Слабые и неизвестные ссылки" на этой странице
Я знал разницу между этими двумя. Но мне любопытно, есть ли веская причина для предпочтения unowned
чем weak
? я думаю weak
гораздо безопаснее, и мы всегда можем написать [weak obj]
и необязательная проверка привязки, не задумываясь о возможности существования obj
,
Это связано с соображениями производительности или с чем-то, что я пропустил? Или это полностью нормально использовать weak
вместо unowned
все время?
1 ответ
Слабые ссылки автоматически устанавливаются на 'nil'
как только объект, на который они указывают, освобождается. Чтобы это было возможно в Swift, они должны быть объявлены как 'var'
и необязательно:
class SomeOtherClass {
weak var weakProperty: SomeClass?
}
Это хорошо, если 'weakProperty'
может стать 'nil'
в то время как случай 'SomeOtherClass'
еще жив, и мы хотим проверить это перед использованием (делегаты - один из таких примеров). Но что, если какая-то ссылка никогда не будет логически 'nil'
а мы все еще хотим предотвратить сохранение цикла? В Objective-C любая ссылка на объект может быть 'nil'
(и обмен сообщениями 'nil'
всегда молча терпит неудачу) поэтому дилеммы нет, мы всегда используем 'weak'
, Но у Свифта нет ниловых ссылок вообще. Мы используем опционы для чего-то, что может семантически не иметь ценности. Но мы не должны быть вынуждены использовать опционы для чего-то, что всегда должно иметь значение, просто чтобы иметь возможность разорвать цикл сохранения. Такая практика идет вразрез с предполагаемой семантикой необязательных. Это где 'unowned'
приходит. Он поставляется в двух вариантах - 'unowned(safe)'
а также 'unowned(unsafe)
". Последнее опасно и эквивалентно 'assign'
а также 'unsafe_unretained'
из Objective-C. Но первый, который является стандартным (по крайней мере, во время отладки, не уверенный, оптимизируют ли они его как "unowned(небезопасный)" в сборках релизов), надежно завершит работу нашего приложения, если указанный объект будет преждевременно освобожден. Конечно, наше приложение будет аварийно завершать работу, если что-то пойдет не так, но отладку гораздо проще, чем молчаливо. Он должен молча терпеть неудачу только тогда, когда мы действительно этого хотим (в этом случае мы будем использовать 'weak'
)
ARC
- Automatic Reference Counting
это механизм, который управляет памятью, который применим для reference
введите [О программе]. Объект освобождается только тогда, когда на нем 0 ссылок.
Strong reference
- установлен по умолчанию, и этот тип безопасно использовать в линейных отношениях (нет цикла)
Retain cycle
- это ситуация, когда каждый объект имеет сильные ссылки друг на друга
Сломать Retain cycle
: weak
а также unowned
. Оба они не увеличивают счетчик удержания объекта на+1
, и есть следующие отличия
Weak reference
- Когда объект ссылки освобождается (nil
), ARC
установить weak
ссылка на nil
тоже. Поэтомуweak
ссылка - это переменная var
(не может быть постоянным let
) [var vs let], поэтому это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(unsafe)
действует UnsafePointer
что может создать dangling pointer
. __unsafe_unretained
от Objective-C
. Это своего рода прямой доступ к памяти, которыйARC
не обрабатывает. Это может вызвать неожиданное поведение, а не просто сбой. У него лучшая производительность
EXC_BAD_ACCESS