Когда вы объявляете @property
, компилятор автоматически синтезирует переменную с префиксом подчеркивания, метод получения и метод установки.
@interface MyClass ()
@property(strong, nonatomic) NSString *myString;
@end
В этом примере компилятор будет определять переменную как _myString
, геттер как
-(NSString *)myString
и сеттер как
-(void)setMyString:(NSString *)string
Ключевые слова после "@property" (strong, nonatomic)
определяют атрибуты свойства. strong
, значение по умолчанию, подразумевает владение, что означает, что в этом случае экземпляры MyClass
будут нести ответственность за сохранение / освобождение своих соответствующих объектов myString
. nonatomic
означает, что переменная не всегда является допустимым значением в многопоточной среде, например, если геттер вызывается одновременно с сеттером.
Кроме того, компилятор будет обрабатывать точечный синтаксис, используемый для извлечения / установки переменных экземпляра, как вызовы соответствующих методов получения / установки. Следовательно, учитывая экземпляр MyClass
MyClass *exampleClass = [[MyClass alloc] init];
Оба следующих утверждения эквивалентны:
NSString *string1 = example.myString; // dot syntax
NSString *string1 = [example myString]; // explicit call to the getter method
Для дальнейшего чтения ознакомьтесь с Programming с Руководством по Objective-C.
Что касается ваших конкретных вопросов:
1. Какой вообще смысл их там объявлять, если мы можем просто создать два свойства?
На самом деле не рекомендуется явно объявлять переменные как общедоступные в ваш MyClass.h
файл (или в большинстве других случаев). Вместо этого объявление их как свойств автоматически создает частную переменную (и методы доступа), что немного упрощает соблюдение лучших практик ООП. Так что нет смысла объявлять
// MyClass.h
@interface MyClass : NSObject {
NSString *myString // public variables not good
}
Также из-за того, что я сказал выше относительно синтаксиса точек, если вы используете self.myString
внутри MyClass.m
или instanceOfMyClass.myString
извне, общедоступная переменная myString
никогда не будет затронута, потому что синтезируемая переменная называется _myString
.
2. Зачем создавать две переменные экземпляра И свойства, чтобы они соответствовали им?
См. Выше - вам не нужны две переменные экземпляра, только одна.
3. Я знаю, что мы можем объявить переменные в .m вместо этого, чтобы сохранить их частными для класса и всего, что является его подклассом. Какая здесь разница? Я чувствую, что мне не хватает основ. Есть ли упрощенный способ представить все это в перспективе?
Если вы объявляете переменные конфиденциально в @implementation
части вашего .m
файла, компилятор не сможет помочь вам, синтезируя геттеры и сеттеры. Даже как частные методы, геттеры и сеттеры могут помочь снизить сложность вашего кода, например, проверяя правильность значений переменных. (Примечание: вы можете переопределить методы доступа.)
// MyClass.m
@interface MyClass () // private interface
@property(nonatomic, strong) NSString *myString;
@end
@implementation MyClass {
// no more need for private variables!
// compiler will synthesize NSString *_myString and accessors
}
-(void)setMyString:(NSString *)string { // overwrite setter
// no empty strings allowed in our object (for the sake of example)
NSAssert([string length] > 0, @"String must not be empty");
// assign private instance variable in setter
_myString = string;
}
@end
Таким образом, даже когда вы создаете подкласс MyClass
, подкласс унаследует методы получения и установки, которые были синтезированы для нас компилятором.
person
Morgan Chen
schedule
31.10.2014
@property float heightInMeters;
, компилятор синтезирует соответствующую переменную экземпляра_heightInMeters
(с добавленным подчеркиванием). Но уже есть много вопросов и ответов по этой теме, если вы ищете переменные свойства и экземпляра, вы должны найти все, что вам нужно. - person Martin R   schedule 31.10.2014