Есть два новых атрибута управления памятью для свойств, введенных ARC, strong
и weak
.
Помимо copy
, который, очевидно, является чем-то совершенно другим, существуют ли различия между strong
vs retain
и weak
vs assign
?
С моей точки зрения, единственное различие здесь в том, что weak
присваивает указателю nil
, а assign
не будет, что означает, что программа выйдет из строя, когда я отправлю сообщение указателю, выпущенный. Но если я использую weak
, этого никогда не произойдет, потому что сообщение, отправленное на nil
, ничего не сделает.
Я не знаю никаких различий между strong
и retain
.
Есть ли какая-то причина, по которой я должен использовать assign
и retain
в новых проектах, или они являются устаревшими?
Из Переход к заметкам о выпуске ARC (пример в разделе атрибутов свойств).
// The following declaration is a synonym for: @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;
Итак, strong
совпадает с retain
в объявлении свойства.
Для проектов ARC я бы использовал strong
вместо retain
, я бы использовал assign
для примитивных свойств C и weak
для слабых ссылок на объекты Objective-C.
assign
для объекта. Вы должны использовать weak
или unsafe_unretained
(что небезопасно, очевидно), если вы не хотите сохранять свойство.
assign
компиляции для меня хорошо в проектах ARC с целью развертывания 4.0.
После прочтения стольких статей Stackoverflow и демо-приложений для проверки атрибутов свойств переменной я решил собрать все данные атрибутов вместе:
Ниже приведена подробная ссылка на статью, в которой вы можете найти вышеупомянутые все атрибуты, которые определенно помогут вам. Большое спасибо всем людям, которые дают лучшие ответы здесь!
1.strong(iOS4 = сохранить)
Пример:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.weak -
Пример:
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
Сильное и слабое объяснение, Благодаря BJ Homer:
Представьте, что наш объект - собака, и собака хочет убежать (быть перераспределена).
Сильные указатели похожи на поводка на собаке. Пока у вас есть привязь к собаке, собака не убежит. Если пять человек прикрепите их привязь к одной собаке (пять сильных указателей на один объект), то собака не убежит, пока все пять поводков не будут отсоединены.
Слабые указатели, с другой стороны, похожи на маленьких детей, указывающих на собака и сказать: "Смотрите, собака!" Пока собака все еще находится на поводка, маленькие дети все еще могут видеть собаку, и они все равно будут указывать к нему. Однако, как только все поводки отсоединяются, собака бежит независимо от того, сколько маленьких детей указывают на это.
Как только последний сильный указатель (поводок) больше не указывает на объект, объект будет освобожден, и все слабые указатели будут обнулено.
Когда мы используем слабые?
Единственный раз, когда вы хотите использовать слабый, - это если вы хотите избежать циклов сохранения (например, родительский элемент сохраняет дочерний элемент, а дочерний элемент сохраняет родительский элемент, поэтому он не освобождается).
3.retain = strong
Пример:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.assign
Пример:
@property (nonatomic, assign) NSString *address;
@synthesize address;
Насколько я знаю, strong
и retain
являются синонимами, поэтому они делают точно то же самое.
Тогда weak
почти как assign
, но автоматически устанавливается на nil после того, как объект, указывающий на, освобождается.
Это означает, что вы можете просто заменить их.
Однако есть один специальный случай, с которым я столкнулся, где мне пришлось использовать assign
, а не weak
. Пусть говорят, что мы имеем два свойства delegateAssign
и delegateWeak
. В обоих хранится наш делегат, который владеет нами, имея только сильную ссылку. Делегат освобождается, поэтому наш метод -dealloc
также вызывается.
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething];
[delegateAssign doSomething];
}
Делегат уже находится в процессе освобождения, но все еще не полностью освобожден. Проблема в том, что ссылки weak
на него уже недействительны! Свойство delegateWeak
содержит nil, но delegateAssign
содержит действительный объект (со всеми уже выпущенными и сведенными свойствами, но все еще действительными).
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething]; // Does nothing, already nil.
[delegateAssign doSomething]; // Successful call.
}
Это довольно частный случай, но он показывает нам, как работают эти переменные weak
и когда они сбрасываются.
Документ Clang на Objective-C Автоматический подсчет ссылок (ARC) четко объясняет квалификаторы и модификаторы владения:
Есть четыре квалификатора собственности:
- __ autoreleasing
- __ сильный
- __ * unsafe_unretained *
- __ слабый
Тип является нетривиальной собственностью, если он квалифицирован __autoreleasing, __strong или __weak.
Затем для объявленного свойства есть шесть модификаторов собственности:
- assign подразумевает __ * unsafe_unretained * право собственности.
- copy подразумевает владение __strong, а также обычное поведение семантики копирования в сеттер.
- сохранить подразумевает __strong собственность.
- сильный означает __strong собственность.
- * unsafe_unretained * подразумевает __ * unsafe_unretained * право собственности.
- слабый подразумевает владение __weak.
За исключением слабых, эти модификаторы доступны в режимах, отличных от ARC.
Семантика мудрая, квалификаторы собственности имеют разное значение в пяти управляемых операциях: Чтение, Назначение, Инициализация, Уничтожение и Перемещение, в которых большую часть времени мы только заботимся о разнице в операции Назначения.
Присвоение происходит при оценке оператора присваивания. семантика варьируется в зависимости от квалификации:
- Для объектов __strong новый указатель сначала сохраняется; во-вторых, lvalue загружается примитивной семантикой; в-третьих, новый указатель хранится в lvalue с примитивной семантикой; и, наконец, старый пункт был выпущен. Это не выполняется атомарно; внешняя синхронизация должна использоваться, чтобы сделать это безопасным в условиях одновременных нагрузок и хранилищ.
- Для объектов __weak значение lvalue обновляется, чтобы указывать на нового pointee, если новый pointee не является объектом, который в настоящее время проходит освобождение, и в этом случае lvalue обновляется до нулевого указателя. Это должно выполняться атомарно по отношению к другим назначениям объекту, чтению с объекта и окончательному выпуску нового указателя.
- Для объектов __ * unsafe_unretained * новый указатель хранится в lvalue с использованием примитивной семантики.
- Для __авторизующих объектов новый указатель сохраняется, автореализован и сохраняется в lvalue с использованием примитивной семантики.
Другое отличие в Чтении, Инициировании, Разрушении и Передвижении, см. Раздел 4.2 Семантика в документе.
Пример: @property (сильный, неатомный) ViewController * viewController;
@synthesize viewController;
По умолчанию автоматически устанавливается и устанавливается на nil
Пример: @property (слабый, неатомный) IBOutlet UIButton * myButton;
@synthesize myButton;
Различия между сильным и удержанием:
Различия между слабым и присваиванием:
unsafe_unretained
три новых атрибута управления памятью для свойств:strong
,weak
иunsafe_unretained
.weak
иstrong
) и 4 квалификатора времени жизни переменной (__strong
,__weak
,__unsafe_unretained
,__autoreleasing
). Смотрите примечания ARC ниже.