Чи потрібні оголошені властивості відповідної змінної екземпляра?


101

Чи потрібні властивості в Objective-C 2.0 оголошувати відповідну змінну екземпляра? Наприклад, я звик робити щось подібне:

MyObject.h

@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

MyObject.m

@implementation
@synthesize name;
@end

Однак що робити, якщо я зробив це замість цього:

MyObject.h

@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end

Чи все-таки це дійсно? І чи якимось чином він відрізняється від мого попереднього прикладу?


Чому другий "MyObject.h" жирним шрифтом не "MyObject.m"?
Ríomhaire

Відповіді:


93

Якщо ви використовуєте програму Modern Objective-C Runtime (це iOS 3.x або більше, або 64-бітний Snow Leopard або більше), вам не потрібно визначати ivars для своїх властивостей у таких випадках.

Коли ви маєте @synthesizeвласність, ivar фактично буде синтезований і для вас. Це оточує сценарій "крихкого івара". Детальніше про це ви можете прочитати на Какао з любов'ю


71

У своєму інтерфейсі ви можете офіційно оголосити змінну екземпляра між дужками, або за @propertyмежами дужок, або обох. Так чи інакше, вони стають атрибутами класу. Різниця полягає в тому, що якщо ви заявляєте @property, ви можете реалізувати за допомогою @synthesize, який автоматично кодує ваш геттер / сетер для вас. Автоматичний кодер встановить ініціалізацію цілих чисел і плаває, наприклад, до нуля. ЯКЩО ви оголосите змінну екземпляра, і НЕ вказуєте відповідну @property, тоді ви не можете використовувати @synthesizeі потрібно написати власний геттер / сеттер.

Ви завжди можете перекрити автоматично кодований геттер / сетер, вказавши свій власний. Це зазвичай робиться з managedObjectContextвластивістю, яка ліниво завантажена. Таким чином, ви декларуєте свою managedObjectContextвласність, але потім також пишете -(NSManagedObjectContext *)managedObjectContextметод. Нагадаємо, що метод "getter" - метод, який має те саме ім'я, що і змінна / властивість екземпляра.

Метод @propertyдекларування також дозволяє вам отримати інші параметри, наприклад, retainта readonly, яких метод декларування змінної інстанції не має. В основному, ivarце старий спосіб, і @propertyрозширює його, і робить його більш вигадливим / легшим. Ви можете посилатися на будь-яке використання self. префікса чи ні, це не має значення, поки ім'я є унікальним для цього класу. В іншому випадку, якщо ваш суперклас має те саме ім’я властивості, що і ви, тоді вам слід сказати або як self.name або super.name, щоб вказати, про яке ім’я ви говорите.

Таким чином, ви побачите все менше і менше людей, які оголошують ivars між дужками, і замість цього переходите до того, щоб просто вказати @property, а потім зробити @synthesize. Ви не можете зробити @synthesizeу своїй реалізації без відповідного @property. Synthesizer знає , який тип атрибута це з @propertyспецифікації. Оператор синтезу також дозволяє перейменовувати властивості, так що ви можете посилатися на властивість одним ім'ям (скороченням) всередині вашого коду, але зовні у файлі .h використовувати повне ім’я. Однак із справді класним автозаповненням, яке зараз має XCode, це є меншою перевагою, але все-таки є.

Сподіваюсь, це допоможе усунути всю плутанину та дезінформацію, яка пливе там.


Тепер днями не обов’язково писати @synthesize. Отже, як ця відповідь справедлива в такому випадку!
Raaz

Ви НЕ ХОЧУТИ оголосити <code> @property ... @ синтезувати </code>. Використання синтезу позбавляє вас від необхідності писати геттер / сетер у вашій реалізації. Якщо ви не синтезуєте, тоді ви повинні
скотити

2
@PapaSmurf Це неправильно. Ви можете використовувати @property, а не використовувати @synthesizeі не реалізовувати їх самостійно. Компілятор автоматично synthesizeдля вас, без того більше писати.
jbrennan

8

він працює обома способами, але якщо ви не оголосите їх фігурними дужками, ви не побачите їх значень у налагоджувачі в xcode.


3

З документації:

Взагалі поведінка властивостей однакова як для сучасних, так і для застарілих режимів (див. "Версії та платформи виконання" в Посібнику з програмування об'єктивного C). Є одна ключова відмінність: сучасний час виконання підтримує синтез змінних екземплярів, тоді як застарілий час виконання цього не робить.

Щоб @synthesize працював у застарілому режимі, потрібно або надати змінну примірника з тим самим іменем та сумісним типом властивості, або вказати іншу існуючу змінну екземпляра в операторі @synthesize. Із сучасним режимом виконання, якщо ви не надаєте змінну екземпляра, компілятор додає одну для вас.


3

Якщо ви використовуєте XCode 4.4 або пізнішої версії, він створить код, який синтезує змінний код для вас.

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

@property (nonatomic, strong) NSString *name;

він створить синтезуючий код як

@synthesize name = _name;

і ви можете отримати доступ до змінної екземпляра, використовуючи _name, це аналогічно декларуванню

NSString* _name

але якщо ви оголосите властивість лише для читання, це подобається

@property (nonatomic, strong, readonly) NSString *name;

це створить код

@synthesize name;

або

@synthesize name = name; 

Таким чином, вам слід отримати доступ до ім’я миттєвої змінної з префіксом "_" будь-яким способом ви можете написати власний синтезуючий код, тоді компілятор генерує код для вас. можна писати

@synthesize name = _name;

1

Мова програмування Objective-C: Директиви про реалізацію власності

Існують відмінності у поведінці синтезу аксесуарів, які залежать від часу виконання (див. Також "Різниця часу виконання"):

  • Для застарілих циклів виконання змінні екземпляри повинні бути вже оголошені в блоці @interface поточного класу. Якщо існує змінна примірник з тим самим іменем, що і властивість, і якщо її тип сумісний з типом властивості, він використовується, інакше ви отримуєте помилку компілятора.

  • Для сучасних умов виконання (див. "Версії та платформи виконання" в Посібнику з програмування Objective-C) змінні екземплярів синтезуються за потребою. Якщо змінна примірник з тим самим іменем вже існує, вона використовується.

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