@ властивість зберігати, призначати, копіювати, неатомічно в Objective-C


214

Як хтось, що є новим у Objective-C, може хтось подати мені огляд збереження, присвоєння, копіювання та будь-яких інших, які я відсутні, які відповідають директиві @property? Що вони роблять і чому я хочу використовувати один над іншим?


1
Назва Apple для цього - "атрибути" або "атрибути властивості"
nevan king

Відповіді:


273

Стаття, на яку посилається MrMage, більше не працює. Отже, ось що я дізнався за своїм (дуже) коротким часом кодування в Objective-C:

неатомічний та атомний - за замовчуванням "атомний". Завжди використовуйте "неатомічний". Я не знаю чому, але в книзі, яку я прочитав, було сказано, що "рідко є причина" використовувати "атомну". (BTW: Книга, яку я читав, - це книга BNR "Програмування iOS".)

readwrite vs. readonly - за замовчуванням "readwrite". Коли ви @synthesize, для вас будуть створені і геттер, і сетер. Якщо ви використовуєте "тільки для читання", жоден сетер не буде створений. Використовуйте його для значення, яке ви не хочете ніколи змінювати після встановлення об'єкта.

зберегти проти копіювання проти присвоїти

  • "призначити" - це за замовчуванням. У сеттері, створеному @synthesize, значення буде просто присвоєно атрибуту. Я розумію, що "призначити" слід використовувати для атрибутів, що не вказують.
  • "утримувати" потрібно, коли атрибут є вказівником на об'єкт. Сеттер, згенерований @synthesize, збереже (він також додасть кількість збереження) об'єкта. Потрібно буде звільнити об’єкт, коли закінчите з ним.
  • "копія" потрібна, коли об'єкт змінюється. Використовуйте це, якщо вам потрібне значення об'єкта таким, яким воно є в даний момент, і ви не хочете, щоб це значення відображало будь-які зміни, внесені іншими власниками об'єкта. Вам потрібно буде звільнити об’єкт, коли ви закінчите його, оскільки ви зберігаєте копію.

@Blamdarot - чи потрібно також випустити його з ARC
Dejell

10
@Odelya - Ні. Якщо ви випустите під час використання ARC, я вважаю, ви отримаєте помилку компілятора.
Blamdarot

52
"Завжди використовуйте неатомічний" - це погана порада. Ви повинні знати, від чого відмовляєтеся, коли вживаєте неатомічні.
Джессі Русак

7
Домовились. Зокрема, багато людей, здається, не знають, що неатомічні значення не отримують-автоматично вивільняються геттером. неатомічний часто доречний, але програмування культового культу рідко є.
Catfish_Man

9
Порадити залишити дефолт atomicтак само погано, як і порадити nonatomic. Жоден вибір не є "правильним", тому мовні дизайнери вибрали безпечніше двох рішень. Насправді nonatomicце найкращий вибір, оскільки він упускає надзвичайно дорогі замки з нитками. Єдиною причиною використання atomicє те, якщо ваше майно може бути встановлено з декількох потоків (у такому випадку його пропуск може призвести до надмірного випуску або витоку).
Адам Каплан

295

Перш ніж дізнатися про атрибути @property, слід знати, у чому полягає використання @property.

  • @property пропонує спосіб визначити інформацію, яку призначений для інкапсуляції класу. Якщо ви оголосите об’єкт / змінну за допомогою @property , то цей об'єкт / змінна буде доступна для інших класів, що імпортують його клас.

  • Якщо ви оголошуєте об'єкт за допомогою @property у файлі заголовка, вам доведеться його синтезувати за допомогою @synthesize у файлі реалізації. Це робить об'єкт KVC сумісним . За замовчуванням компілятор синтезує методи аксесуарів для цього об’єкта.

  • Методами аксесуарів є: сетер та геттер.

Приклад: .h

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

.m

@implementation XYZClass
@synthesize name;
@end

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

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

    атомний, неатомний, зберегти, скопіювати, лише для читання, перечитати, призначити, сильний, getter = метод, setter = метод, небезпечний_незахищений

  • атомний - це поведінка за замовчуванням. Якщо об’єкт оголошений атомним, він стає безпечним для потоків. Захист потоку означає, що за часом лише одна нитка певного екземпляра цього класу може мати контроль над цим об'єктом.

Якщо потік виконує метод getter, то інший потік не може виконати метод setter на цьому об'єкті. Це повільно.

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

З цієї причини швидше отримати доступ до неатомної властивості, ніж до атомного.

@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, ви можете оголосити властивість лише заново.

Компілятор генерує геттер, але не сетер.

@property (readonly) NSString *name;
  • readwrite - це поведінка за замовчуванням. Не потрібно чітко вказувати атрибут readwrite.

Це протилежне лише читання.

@property (readwrite) NSString *name;
  • Призначати буде генерувати сеттер, який присвоює значення змінній екземпляру безпосередньо, а не копіює або зберігає його. Це найкраще для примітивних типів, таких як NSInteger та CGFloat, або об'єктів, якими ви безпосередньо не володієте, наприклад, делегатів.

Пам’ятайте, що утримування та призначення є в основному взаємозамінними, коли ввімкнено збирання сміття.

@property (assign) NSInteger year;
  • міцний є заміною утримувати.

Він поставляється з ARC.

@property (nonatomic, strong) AVPlayer *player; 
  • getter = метод Якщо ви хочете використовувати інше ім'я для методу getter, можна вказати власну назву, додавши до властивості атрибути.

У випадку булевих властивостей (властивості, які мають значення YES або NO), метод getter починається зі слова "є"

@property (getter=isFinished) BOOL finished;
  • setter = метод Якщо ви хочете використовувати інше ім'я для методу setter, можна вказати власну назву, додавши до властивості атрибути.

Метод повинен закінчуватися двокрапкою.

@property(setter = boolBool:) BOOL finished;
  • небезпечно Є кілька класів у Cocoa та Cocoa Touch, які ще не підтримують слабкі посилання, а це означає, що ви не можете оголосити слабку властивість або слабку локальну змінну, щоб відстежувати їх. Ці класи включають NSTextView, NSFont і NSColorSpace тощо. Якщо вам потрібно використовувати слабку посилання на один з цих класів, ви повинні використовувати небезпечну посилання.

Небезпечна посилання схожа на слабку посилання тим, що вона не підтримує пов'язаний об’єкт живим, але він не буде встановлений на нуль, якщо об'єкт призначення буде розміщений.

@property (unsafe_unretained) NSObject *unsafeProperty;

Якщо вам потрібно вказати кілька атрибутів, просто включіть їх як список, розділений комами, як-от так:

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

Крім того, слабкий означає, що немає посилання на об'єкт, на який посилається, а на те, що він взагалі посилається або взагалі не посилається на нього. На кшталт "так, щось на мене посилається" проти "9 посилань на мене існують" (що таке сильне).
Алекс Заватоне

6
Ігноруйте рядок у відповіді щодо збирання сміття, оскільки збирання сміття в Mac OS X застаріле і не існує в iOS за документацією Apple .
Василь Бурк

4
"Примітка. Атомність властивості не є синонімом безпеки потоку об'єкта." - від developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
jk7

1
«Якщо ви оголошуєте об'єкт , використовуючи @propertyв заголовки, то ви повинні синтезувати його , використовуючи @synthesizeв файлі реалізації.» Не завжди. Наприклад, "За замовчуванням readwriteвластивість буде підтримуватися змінною екземпляра, яка знову буде автоматично синтезована компілятором." Від док .
Франклін Ю

4
@liza Це відмінна відповідь. Чому це не прийнята відповідь. Це дає набагато більш обізнане пояснення, ніж прийнята на даний момент відповідь. Я іноді не розумію StackOverflow?
Чарльз Робертсон

149

Прочитавши багато статей, я вирішив зібрати всю інформацію про атрибути:

  1. атомний // за замовчуванням
  2. неатомічний
  3. strong = зберегти // за замовчуванням
  4. слабкий = небезпечний
  5. зберегти
  6. призначити // за замовчуванням
  7. небезпечно
  8. копія
  9. лише для читання
  10. readwrite // за замовчуванням

Нижче наводиться посилання на детальну статтю, де ви можете знайти ці атрибути.

Велике спасибі всім людям, які дають найкращі відповіді тут !!

Змінні атрибути властивості або модифікатори в iOS

Ось зразковий опис із статті

  1. атомно -атомічний означає, що лише один потік має доступ до змінної (статичний тип). -Atomic є безпечним для ниток. -але це повільно в продуктивності -атомічне поведінка за замовчуванням -Атомічні аксесуари в не зібраному сміттям середовищі (тобто при використанні утримувати / випускати / автовипускати) використовуватимуть замок, щоб переконатися, що інша нитка не заважає правильному налаштуванню / отриманню вартості. - це насправді не ключове слово.

Приклад:

@property (retain) NSString *name;

@synthesize name;
  1. неатомічний —Нонатомічний означає, що декілька потоків отримують доступ до змінної (динамічний тип). -Ненатомічна - це нитка небезпечна. -але це швидкодієздатність -Ненатомічне НЕ є поведінкою за замовчуванням, нам потрібно додати неатомічне ключове слово в атрибут властивості. -це може призвести до несподіваної поведінки, коли два різні процеси (потоки) отримують доступ до однієї і тієї ж змінної одночасно.

Приклад:

@property (nonatomic, retain) NSString *name;

@synthesize name;

Поясніть:

Припустимо, є властивість атомного рядка під назвою "ім'я", і якщо ви називаєте [self setName: @ "A"] з потоку A, зателефонуйте [self setName: @ "B"] з потоку B, а виклик [self name] з нитка C, тоді всі операції над різною ниткою будуть виконуватися послідовно, тобто якщо один потік виконує сеттер або геттер, то інші потоки будуть чекати. Це робить властивість "name" для читання / запису властивості безпечною, але якщо інший потік D викликає [випуск імені] одночасно, ця операція може призвести до збоїв, оскільки тут не задіяний виклик сеттера / геттера. Що означає, що об'єкт є безпечним для читання / запису (ATOMIC), але не є безпечним для потоків, оскільки інші потоки можуть одночасно надсилати об'єкту будь-який тип повідомлень. Розробник повинен забезпечити безпеку ниток для таких об’єктів.

Якщо властивість "name" була неатомічною, то всі потоки в наведеному вище прикладі - A, B, C і D будуть виконуватися одночасно, створюючи будь-який непередбачуваний результат. У разі атомного, будь-який з A, B або C виконає спочатку, але D все ще може виконуватися паралельно.

  1. strong (iOS4 = retain) -це каже: "тримайте це в купі, поки я більше не вказую на це" - в інших словах "Я власник, ви не можете вирішити це перед тим, як націлитись на те саме, що і зберегти" - Ви використовуєте сильний, лише якщо вам потрібно зберегти об'єкт. -За замовчуванням усі змінні екземпляри та локальні змінні є сильними покажчиками. -Зазвичай ми використовуємо сильні для UIViewControllers (батьки елемента користувальницького інтерфейсу) -strong використовується з ARC, і це в основному допомагає вам, не турбуючись про кількість збережених об'єктів. ARC автоматично випускає його для вас, коли ви закінчите з ним. Використання ключового слова сильним означає, що ви володієте об'єктом.

Приклад:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;
  1. слабкий (iOS4 = unsafe_unretain) - він говорить "зберігайте це до тих пір, поки хтось інший вказує на нього сильно" - те саме, що призначати, не зберігати або звільняти -А "слабке" посилання є посиланням, яке ви не зберігаєте. -Зазвичай ми використовуємо слабкі для IBOutlets (UIViewController's Childs). Це працює, тому що дочірній об’єкт повинен існувати лише до тих пір, як це робить батьківський об'єкт. -слабка посилання - це посилання, що не захищає посилальний об'єкт від збирання сміттєзбірником. - Слабкий, по суті, присвоєний, невлаштований властивість. За винятком випадків, коли об'єкт розміщений, слабкий покажчик автоматично встановлюється на нуль

Приклад:

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

@synthesize myButton;

Сильне і слабке пояснення, завдяки BJ Homer :

Уявіть, наш об’єкт - собака, і що собака хоче втекти (бути розселеною). Сильні покажчики - як повідок на собаці. Поки ви прив’язуєте повідку до собаки, собака не втече. Якщо п’ять людей прив’язують повідку до однієї собаки, (п’ять сильних вказівників на один об’єкт), то собака не втече, поки всі п’ять повідців не від'єднаються. З іншого боку, слабкі вказівники - це як маленькі діти, що вказують на собаку і говорять: "Дивись! Собака!" Поки собака все ще на повідку, маленькі діти ще можуть побачити собаку, і вони все одно вкажуть на неї. Як тільки всі повідці відриваються, собака тікає незалежно від того, скільки маленьких діток на неї вказують. Як тільки останній сильний покажчик (повідок) більше не вказує на об’єкт, об’єкт буде розміщений, і всі слабкі покажчики будуть нульовими. Коли ми використовуємо слабкі? Єдиний раз, коли ви хочете використовувати слабкі, це якщо ви хочете уникнути циклів утримування (наприклад, батько зберігає дитину, а дитина зберігає батьків, тому жоден з них не звільняється).

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

Приклад:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. правонаступник -Прісвоіть за замовчуванням і просто виконує призначення змінного -Прісвоіть є атрибутом властивості , яке указует компілятор , як синтезувати реалізації установки властивостей Я б використовувати правонаступник для C примітивних властивостей і слабкий для слабких посилань на об'єкти Objective-C.

Приклад:

@property (nonatomic, assign) NSString *address;

@synthesize address;
  1. небезпечно

    -unsafe_unretain - це кваліфікатор права власності, який повідомляє ARC, як вставляти виклики утримувати / звільняти -unsafe_unretain - це версія ARC присвоєння.

Приклад:

@property (nonatomic, unsafe_unretained) NSString *nickName;

@synthesize nickName;
  1. копія -копія потрібна, коли об’єкт змінюється. -copy вказує, що нове значення повинно бути надіслане -копія при призначенні, а старе значення відправлено -випуск. -copy - це як утримувати повертає об'єкт, який ви повинні явно випустити (наприклад, у dealloc) у не зібраному сміттям середовищі. -Якщо ви використовуєте копію, тоді вам все-таки потрібно випустити цю програму у dealloc. -Використовуйте це, якщо вам потрібно значення об’єкта таким, яким воно є в даний момент, і ви не хочете, щоб це значення відображало будь-які зміни, внесені іншими власниками об'єкта. Вам потрібно буде звільнити об’єкт, коли ви закінчите його, оскільки ви зберігаєте копію.

Приклад:

@property (nonatomic, copy) NSArray *myArray;

@synthesize myArray;

2
Я думаю, що після дуги, утримувати більше не використовується.
мерт

1
у повному списку відсутні два варіанти параметрів: сеттер і геттер, які також є єдиними параметрами, необхідними аргументами.
Скотт Чу

strong або зберегти за замовчуванням лише для типу об'єкта. Його не можна використовувати для примітивних типів.
Салех Енам Шогаг

9

Атомна властивість може бути доступна одночасно лише однією ниткою. Це безпечно для ниток . За замовчуванням - атомний. Зауважте, що немає ключового слова атомний

Неатомне означає, що кілька елементів можуть отримати доступ до елемента. Це так нитка небезпечна

Тому слід бути дуже обережним під час використання атомних. Як це впливає на продуктивність вашого коду


3
"Примітка. Атомність властивості не є синонімом безпеки потоку об'єкта." від developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
jk7

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.