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-свойств.