Objective-C ARC: сильный против сохранения и слабого vs assign
Есть два новых атрибута управления памятью для свойств, введенных ARC, strong
и weak
.
Помимо copy
, который, очевидно, является чем-то совершенно другим, существуют ли различия между strong
vs retain
и weak
vs assign
?
С моей точки зрения, единственное различие здесь в том, что weak
присваивает указателю nil
, а assign
не будет, что означает, что программа выйдет из строя, когда я отправлю сообщение указателю, выпущенный. Но если я использую weak
, этого никогда не произойдет, потому что сообщение, отправленное на nil
, ничего не сделает.
Я не знаю никаких различий между strong
и retain
.
Есть ли какая-то причина, по которой я должен использовать assign
и retain
в новых проектах, или они являются устаревшими?
Ответы
Ответ 1
Из Переход к заметкам о выпуске 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.
Ответ 2
После прочтения стольких статей Stackoverflow и демо-приложений для проверки атрибутов свойств переменной я решил собрать все данные атрибутов вместе:
- atomic//default
- неатомической
- strong = сохранить//по умолчанию
- слабый
- сохранить
- присваивать //default
- unsafe_unretained
- Копия
- только для чтения
- readwrite//default
Ниже приведена подробная ссылка на статью, в которой вы можете найти вышеупомянутые все атрибуты, которые определенно помогут вам.
Большое спасибо всем людям, которые дают лучшие ответы здесь!
Измененные атрибуты свойств или модификаторы в iOS
1.strong(iOS4 = сохранить)
- он говорит: "Храните это в куче, пока я больше не укажу на это"
- Другими словами: "Я владелец, вы не можете отменить это до того, как цель будет прекрасна с тем же успехом, что и"
- Вы используете сильные, только если вам нужно сохранить объект.
- По умолчанию все переменные экземпляра и локальные переменные являются сильными указателями.
- Обычно мы используем сильные для UIViewControllers (родители элементов пользовательского интерфейса).
- strong используется с ARC, и это в основном помогает вам, не заботясь о сохранении счета объекта. ARC автоматически освобождает его для вас, когда вы закончите с ним. Использование ключевого слова strong означает, что вы владеете объектом.
Пример:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.weak -
- он говорит: "держи это, пока кто-то еще указывает на это сильно"
- то же самое, что и назначение, не сохранять и не выпускать
- "Слабая" ссылка - это ссылка, которую вы не сохраняете.
- Обычно мы используем слабые для IBOutlets (дочерние элементы UIViewController). Это работает, потому что дочерний объект должен существовать только до тех пор, пока выполняется родительский объект.
- Слабая ссылка - это ссылка, которая не защищает ссылочный объект от коллекции сборщиком мусора.
- Слабый по существу присваивает, незавершенное свойство. За исключением случаев, когда объект освобождается, слабый указатель автоматически устанавливается на nil
Пример:
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
Сильное и слабое объяснение, Благодаря BJ Homer:
Представьте, что наш объект - собака, и собака хочет убежать (быть перераспределена).
Сильные указатели похожи на поводка на собаке. Пока у вас есть привязь к собаке, собака не убежит. Если пять человек прикрепите их привязь к одной собаке (пять сильных указателей на один объект), то собака не убежит, пока все пять поводков не будут отсоединены.
Слабые указатели, с другой стороны, похожи на маленьких детей, указывающих на собака и сказать: "Смотрите, собака!" Пока собака все еще находится на поводка, маленькие дети все еще могут видеть собаку, и они все равно будут указывать к нему. Однако, как только все поводки отсоединяются, собака бежит независимо от того, сколько маленьких детей указывают на это.
Как только последний сильный указатель (поводок) больше не указывает на объект, объект будет освобожден, и все слабые указатели будут обнулено.
Когда мы используем слабые?
Единственный раз, когда вы хотите использовать слабый, - это если вы хотите избежать циклов сохранения
(например, родительский элемент сохраняет дочерний элемент, а дочерний элемент сохраняет родительский элемент, поэтому он не освобождается).
3.retain = strong
- он сохраняется, старое значение освобождается и присваивается значение сохранения указывает, что новое значение должно быть отправлено
- сохранить при назначении и отправленное старое значение -release
- сохранить то же самое, что и сильный.
- apple говорит, что если вы напишете, сохраните, он будет автоматически преобразован/работает как сильный.
- методы, такие как "alloc", включают неявное "сохранение"
Пример:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.assign
- назначает значение по умолчанию и просто выполняет присвоение переменной
- assign - это атрибут свойства, который сообщает компилятору, как синтезировать реализацию средства установки свойств.
- Я бы использовал назначение для примитивных свойств C и слабый для слабых ссылок на объекты Objective-C.
Пример:
@property (nonatomic, assign) NSString *address;
@synthesize address;
Ответ 3
Насколько я знаю, 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
и когда они сбрасываются.
Ответ 4
неатомический/атомное
- nonatomic намного быстрее, чем атомный
- всегда используйте неатомические, если у вас нет особого требования к атомам, которое должно быть редким (атомарное не гарантирует безопасность потока - только киоски, обращающиеся к свойству, когда он одновременно устанавливается другим потоком)
сильный/слабый/правопреемник
- использовать сильные для сохранения объектов - хотя сохранение ключевого слова является синонимом, лучше использовать сильные вместо этого
- использовать слабый, если вам нужен только указатель на объект, не сохраняя его - полезно избегать циклов сохранения (т.е. делегатов) - он автоматически отключит указатель при выпуске объекта
- использовать назначение для примитивов - точно так же, как и слабый, за исключением того, что не выделяется объект при его выпуске (устанавливается по умолчанию)
(Необязательно)
Копия
- использовать его для создания мелкой копии объекта
- Хорошая практика всегда устанавливать неизменяемые свойства для копирования - поскольку измененные версии могут быть переданы в неизменяемые свойства, копия гарантирует, что вы всегда будете иметь дело с неизменяемым объектом
- Если передается неизменяемый объект, он сохранит его - если переданный объект изменен, он скопирует его
только для чтения
- использовать его для отключения настройки свойства (предотвращает компиляцию кода, если есть нарушение)
- вы можете изменить то, что доставлено получателем, либо изменив переменную напрямую через свою переменную экземпляра, либо внутри самого метода getter
Ответ 5
Документ 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 Семантика в документе.
Ответ 6
Strong:
- Свойство не будет уничтожаться, но только после того, как вы установите свойство на nil, объект будет уничтожен.
- По умолчанию все переменные экземпляра и локальные переменные являются сильными указателями.
- Вы используете сильные, только если вам нужно сохранить объект.
- Обычно мы используем сильные для UIViewControllers (родители элементов пользовательского интерфейса).
- IOS 4 (не-ARC) Мы можем использовать Retain KeyWord
- IOS 5 (ARC) Мы можем использовать сильное ключевое слово
Пример:
@property (сильный, неатомный) ViewController * viewController;
@synthesize viewController;
Слабое
По умолчанию автоматически устанавливается и устанавливается на nil
- Обычно мы используем слабые для IBOutlets (дочерние элементы UIViewController) и делегируем
- то же самое, что и назначение, не сохранять и не выпускать
Пример:
@property (слабый, неатомный) IBOutlet UIButton * myButton;
@synthesize myButton;
Ответ 7
Различия между сильным и удержанием:
- В iOS4 сильное значение равно сохранить
- Это означает, что вы являетесь владельцем объекта и сохраняете его в куче, пока он больше не укажет на него.
- Если вы напишете, сохраните, он автоматически будет работать так же, как сильный
Различия между слабым и присваиванием:
- "Слабая" ссылка - это ссылка, которую вы не сохраняете, и сохраняете ее, пока кто-то еще указывает на нее.
- Когда объект "освобожден", слабый указатель автоматически устанавливается на nil
- Атрибут атрибута "присваивать" сообщает компилятору, как синтезировать реализацию setter-свойств.