@property сохранять, назначать, копировать, неатомически в Objective-C

Как кто-то, кто новичок в Objective-C, может кому-нибудь дать мне обзор сохранения, назначения, копирования и любых других, которые мне не хватает, которые следуют директиве @property? Что они делают и почему я хочу использовать один над другим?

Ответ 1

Статья, связанная с MrMage, больше не работает. Итак, вот что я узнал в моей (очень) короткой кодировке в Objective-C:

неатомный и атомный - "атомный" по умолчанию. Всегда используйте "неатомический". Я не знаю, почему, но в книге, которую я читал, говорилось, что "редко есть причина" использовать "атомную". (BTW: Книга, которую я прочитал, - это книга BNR "Программирование iOS".)

readwrite vs. readonly - "readwrite" является значением по умолчанию. Когда вы @synthesize, и геттер, и сеттер будут созданы для вас. Если вы используете "readonly", сеттер не будет создан. Используйте его для значения, которое вы не хотите изменять после создания объекта.

сохранить vs. copy vs. assign

  • "присваивать" значение по умолчанию. В сеттер, созданный с помощью @synthesize, значение будет просто присвоено атрибуту. Я понимаю, что для атрибутов, отличных от указателей, следует использовать "assign".
  • "Сохранить" необходимо, когда атрибут является указателем на объект. Сеттер, сгенерированный с помощью @synthesize, сохранит (ака добавит счетчик удержания) объекта. Вам нужно будет освободить объект, когда вы закончите с ним.
  • "копировать" необходимо, когда объект изменен. Используйте это, если вам нужно значение объекта, как оно есть в данный момент, и вы не хотите, чтобы это значение отражало любые изменения, сделанные другими владельцами объекта. Вам нужно будет освободить объект, когда вы закончите его, потому что вы сохраняете копию.

Ответ 2

Прежде чем вы узнаете об атрибутах @property, вы должны знать, что такое использование @property.

  • @property предлагает способ определения информации, которую класс должен инкапсулировать. Если вы объявляете объект/переменную с помощью @property, то этот объект/переменная будет доступен для других классов, импортирующих его класс.

  • Если вы объявляете объект с использованием @property в файле заголовка, вам необходимо его синтезировать с помощью @synthesize в файле реализации. Это делает объект совместимым с KVC. По умолчанию компилятор будет синтезировать методы доступа для этого объекта.

  • методы доступа: setter и getter.

Пример: .h

@interface XYZClass : NSObject
@property (nonatomic, retain) NSString *name;
@end

.m

@implementation XYZClass
@synthesize name;
@end

Теперь компилятор будет синтезировать методы доступа для name.

XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:@"liza"]; // first letter of 'name' becomes capital in setter method
  • Список атрибутов @property

    атомный, неатомный, сохраняющий, копирующий, readonly, readwrite, assign, strong, getter = метод, setter = метод, unsafe_unretained

  • atomic - это поведение по умолчанию. Если объект объявлен как атомный, он становится потокобезопасным. Потоковые средства, в то время только один поток конкретного экземпляра этого класса может иметь контроль над этим объектом.

Если поток выполняет метод getter, то другой поток не может выполнить метод setter для этого объекта. Это медленно.

@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
  • неатомический не является потокобезопасным. Вы можете использовать атрибут nonatomic property, чтобы указать, что синтезированные аксессоры просто устанавливают или возвращают значение напрямую, без каких-либо гарантий относительно того, что произойдет, если одно и то же значение будет доступно одновременно из разных потоков.

По этой причине его более быстрый доступ к неатомическому свойству, чем атомный.

@property (nonatomic)NSString *name;   
  • сохранить требуется, когда атрибут является указателем на объект.

Метод setter увеличит количество удержаний объекта, так что он будет занимать память в пуле автоопределений.

@property (retain)NSString *name;
  • копировать. Если вы используете копию, вы не можете использовать сохранение. Использование экземпляра копии класса будет содержать свою собственную копию.

Даже если измененная строка установлена ​​и впоследствии изменена, экземпляр фиксирует любое значение, которое он имеет в момент его установки. Никакие методы сеттера и геттера не будут синтезированы.

@property (copy) NSString *name;

Теперь,

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"]; 

имя останется незатронутым.

  • readonly Если вы не хотите, чтобы свойство было изменено с помощью метода setter, вы можете объявить свойство readonly.

Компилятор будет генерировать геттер, но не сеттер.

@property (readonly) NSString *name;
  • readwrite - это поведение по умолчанию. Вам не нужно явно указывать атрибут readwrite.

Это противоположно readonly.

@property (readwrite) NSString *name;
  • присваивать будет генерировать установщик, который напрямую присваивает значение переменной экземпляра, а не копирует или сохраняет его. Это лучше всего подходит для таких примитивных типов, как NSInteger и CGFloat, или объектов, которые вы не являетесь непосредственно владельцами, например делегатов.

Помните, что сохранение и назначение в основном взаимозаменяемы, когда включена сборка мусора.

@property (assign) NSInteger year;
  • strong является заменой для сохранения.

Он поставляется с ARC.

@property (nonatomic, strong) AVPlayer *player; 
  • getter = method Если вы хотите использовать другое имя для метода getter, его можно указать настраиваемое имя, добавив атрибуты в свойство.

В случае логических свойств (свойств, которые имеют значение ДА или НЕТ), его обычное для метода getter начало со слова "есть"

@property (getter=isFinished) BOOL finished;
  • setter = method Если вы хотите использовать другое имя для метода setter, его можно указать настраиваемое имя, добавив атрибуты к свойству.

Метод должен заканчиваться двоеточием.

@property(setter = boolBool:) BOOL finished;
  • unsafe_unretained Есть несколько классов в Cocoa и Cocoa Touch, которые еще не поддерживают слабые ссылки, а это означает, что вы не можете объявить слабое свойство или слабую локальную переменную, чтобы отслеживать их. Эти классы включают NSTextView, NSFont и NSColorSpace и т.д. Если вам нужно использовать слабую ссылку на один из этих классов, вы должны использовать небезопасную ссылку.

Небезопасная ссылка похожа на слабую ссылку на то, что она не поддерживает связанный с ней объект, но не будет установлен nil, если объект назначения будет освобожден.

@property (unsafe_unretained) NSObject *unsafeProperty;

Если вам нужно указать несколько атрибутов, просто включите их в список, разделенный запятыми, например:

@property (readonly, getter=isFinished) BOOL finished;

Ответ 3

После прочтения многих статей я решил объединить все данные атрибутов:

  • atomic//default
  • неатомической
  • strong = сохранить//по умолчанию
  • weak = unsafe_unretained
  • сохранить
  • присваивать //default
  • unsafe_unretained
  • Копия
  • только для чтения
  • readwrite//default

Ниже приведена ссылка на подробную статью, в которой вы можете найти эти атрибуты.

Большое спасибо всем людям, которые дают лучшие ответы здесь!

Измененные атрибуты свойств или модификаторы в iOS

Вот пример описания из статьи

  • атомное -Atomic означает, что только один поток получает доступ к переменной (статический тип). -Atomic является потокобезопасным. но он медленный в производительности -атомное поведение по умолчанию -Атомные аксессоры в среде, не содержащей мусора (то есть при использовании сохранения/освобождения/авторекламы) будут использовать блокировку для  убедитесь, что другой поток не мешает правильной настройке/получению значения. -Это не является ключевым словом.

Пример:

@property (retain) NSString *name;

@synthesize name;
  1. неатомической -Nonatomic означает, что несколько потоков обращаются к переменной (динамический тип). -Nonatomic - небезопасный поток. но он быстро работает -Nonatomic не является поведением по умолчанию, нам нужно добавить неатомическое ключевое слово в атрибуте свойства. -it может привести к неожиданному поведению, когда два разных процесса (потоки) получают доступ к одной и той же переменной одновременно.

Пример:

@property (nonatomic, retain) NSString *name;

@synthesize name;

Объясняю:

Предположим, что существует свойство атомной строки, называемое "имя", и если вы вызываете [self setName: @ "A" ] из потока A, вызовите [self setName: @ "B" ] из потока B и вызовите [self name] из потока C, тогда вся операция в другом потоке будет выполняться серийно, что означает, что если один поток выполняет setter или getter, тогда другие потоки будут ждать, Это делает свойство "имя" безопасным для чтения/записи, но если другой поток D вызывает [имя выпуска] одновременно, то эта операция может привести к сбою, поскольку здесь нет вызова setter/getter. Это означает, что объект безопасен для чтения/записи (ATOMIC), но не является потокобезопасным, так как другие потоки могут одновременно отправлять любые типы сообщений объекту. Разработчик должен обеспечить безопасность потоков для таких объектов.

Если свойство "name" было неатомным, то все потоки в приведенном выше примере - A, B, C и D будут выполняться одновременно с получением любого непредсказуемого результата. В случае атома, либо один из A, B или C будет выполняться первым, но D может выполняться параллельно.

  1. strong (iOS4 = сохранить) -это говорит: "держи это в куче, пока я больше не буду на это называть" - другими словами: "Я владелец, вы не можете отменить это, прежде чем цель будет прекрасна с тем же успехом, -Вы используете сильный, только если вам нужно сохранить объект. -По умолчанию все переменные экземпляра и локальные переменные являются сильными указателями. -Мы обычно используем сильные для UIViewControllers (родители элементов пользовательского интерфейса) -strong используется с ARC, и это в основном помогает вам, не заботясь о сохранении количества объектов. ARC автоматически освобождает его для вас, когда вы закончите с ним. Использование ключевого слова strong означает, что вы владеете объектом.

Пример:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;
  1. слабый (iOS4 = unsafe_unretained) -это говорит: "держи это, пока кто-то еще указывает на это сильно" - то же самое, что и назначение, отсутствие сохранения или освобождения "Слабая" ссылка - это ссылка, которую вы не сохраняете. -Мы обычно используем слабые для IBOutlets (UIViewController Childs). Это работает, потому что только дочерний объект  должен существовать до тех пор, пока выполняется родительский объект. - слабая ссылка - это ссылка, которая не защищает ссылочный объект от сбора сборщиком мусора. -Weak - это, по сути, назначение, незавершенное свойство. За исключением случаев, когда объект освобождается, слабый указатель автоматически устанавливается на nil

Пример:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Сильное и слабое объяснение, Благодаря BJ Homer:

Представьте, что наш объект - собака, и собака хочет убежать (освободиться). Сильные указатели похожи на поводка на собаке. Пока у вас есть привязь к собаке, собака не убежит. Если пять человек присоединяют свой повод к одной собаке (пять сильных указателей на один объект), то собака не убежит, пока все пять поводков не будут отстранены. Слабые указатели, с другой стороны, похожи на маленьких детей, указывающих на собаку и говорящих "Смотри! Собака!". Пока собака все еще находится на поводке, маленькие дети все еще могут видеть собаку, и они все равно укажут на нее. Однако, как только все поводки отсоединяются, собака убегает независимо от того, сколько маленьких детей указывает на нее. Как только последний сильный указатель (привязка) больше не указывает на объект, объект будет освобожден, и все слабые указатели будут обнулены. Когда мы используем слабый? Единственный раз, когда вы хотите использовать слабый, - это если вы хотите избежать циклов сохранения (например, родительский элемент сохраняет дочерний элемент, а дочерний элемент сохраняет родительский элемент, поэтому он не освобождается).

  1. сохранить= strong -это сохраняется, старое значение освобождается и назначается -retain указывает, что новое значение должно быть отправлено - получить при назначении и отправленное старое значение - освободить -принять то же самое, что и сильный. -apple говорит, что если вы напишете, сохраните, он автоматически преобразуется/работает как сильный. -методы, подобные "alloc", включают неявное "сохранение"

Пример:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. правопреемником -assign является значением по умолчанию и просто выполняет присвоение переменной -assign - атрибут свойства, который сообщает компилятору, как синтезировать реализацию setterter -Я использовал бы назначение для примитивных свойств C и слабых для слабых ссылок на объекты Objective-C.

Пример:

@property (nonatomic, assign) NSString *address;

@synthesize address;
  1. unsafe_unretained

    -unsafe_unretained - это квалификатор собственности, который сообщает ARC, как вставлять вызовы сохранения/освобождения -unsafe_unretained - это ARC-версия назначения.

Пример:

@property (nonatomic, unsafe_unretained) NSString *nickName;

@synthesize nickName;
  1. копия -copy требуется, когда объект изменен. -copy указывает, что новое значение должно быть отправлено -copy при назначении и отправлено старое значение -release. -copy похож на сохранение возвращает объект, который вы должны явно освободить (например, в dealloc) в средах, не связанных с мусором. Если вы используете копию, вам все равно нужно освободить ее в dealloc. -Используйте это, если вам нужно значение объекта, как оно есть в данный момент, и вы не хотите, чтобы это значение отражало любые изменения, сделанные другими  владельцы объекта. Вам нужно будет освободить объект, когда вы закончите его, потому что вы сохраняете копию.

Пример:

@property (nonatomic, copy) NSArray *myArray;

@synthesize myArray;

Ответ 4

Атомное свойство может быть доступно только по одному потоку за раз. Это безопасный поток. По умолчанию это атомный. Обратите внимание, что ключевое слово atom

отсутствует.

Nonatomic означает, что несколько потоков могут получить доступ к элементу. Это поток небезопасный

Поэтому нужно быть очень осторожным при использовании атомарного. Как это влияет на производительность вашего кода.