Свойство - это просто набор из двух методов: геттер и сеттер. Итак, когда вы пишете
@property (strong, nonatomic) NSString *name;
что вы на самом деле говорите, это
- (NSString *)name;
- (void)setName:(NSString *)name;
После этого каждый раз, когда компилятор встречает выражение вида obj.name
, он переводит его в [obj name]
. И каждый раз, когда вы видите выражение типа obj.name = @"hello";
, компилятор переводит его в [obj setName:@"hello"]
.
Следующее, что вы должны убедиться, что свойство ведет себя правильно. У вас есть много вариантов:
- Пишите геттеры и сеттеры вручную, ссылаясь на iVar
- Синтезировать геттер и сеттер
- Автосинтез геттера и сеттера
- Запись пользовательских геттеров и сеттеров
- Используйте
@dynamic
, чтобы избежать предупреждений во время компиляции, потому что вы намерены делать магию во время выполнения. (Действительно, это не то, что вы хотите сделать, потому что сначала вам нужно понять основы.)
Пишите геттеры и сеттеры вручную, ссылаясь на iVar
@interface MyClass : UIView {
NSString *_name;
}
@property (strong, nonatomic) NSString *name;
@end
и в реализации
@implementation MyClass
- (NSString *)name {
return _name;
}
- (void)setName:(NSString *)name {
_name = name;
}
@end
Синтезировать геттер и сеттер
Последний раздел в основном эквивалентен этому
@interface MyClass : UIView {
NSString *_name;
}
@property (strong, nonatomic) NSString *name;
@end
@implementation MyClass
@synthesize name = _name;
@end
Автосинтез геттера и сеттера
На практике вы просто используете "автосинтезирование".
@interface MyClass : UIView
@property (strong, nonatomic) NSString *name;
@end
@implementation MyClass
@end
Это значит,
- если вы просто объявите свойство
- не звоните
@synthesize
или @dynamic
- не реализовывать никаких пользовательских методов получения и установки
приведенный выше код просто создаст iVar с именем _name
и метод получения и установки, который будет выглядеть точно так же, как в первом примере.
Это означает, что первые два и этот разделы эквивалентны, потому что они производят один и тот же код.
Запись пользовательских геттеров и сеттеров
Вот что на самом деле означает термин «динамическое свойство». Например, вы можете захотеть, чтобы имя всегда было в верхнем регистре. Таким образом, вы можете написать свойство как это.
@interface MyClass : UIView {
NSString *_name;
}
@property (copy, nonatomic) NSString *name;
@end
@implementation MyClass
- (NSString *)name {
return _name;
}
- (void)setName:(NSString *)name {
_name = [name uppercaseString];
}
@end
(в приведенном выше коде я изменил strong
на copy
- не волнуйтесь, это в любом случае просто комментарий. И это действительно так, потому что uppercaseString
никогда не будет прежним, он будет всегда быть копией оригинала.)
Это, пожалуй, единственный действительно интересный случай! Например, этот тип свойств - то, что UIKit использует все время, например. text
свойство UILabel
является таким динамическим свойством. Он не только устанавливает некоторые значения iVar, но также гарантирует, что видимый текст на экране также изменится.
@dynamic
свойства
их действительно сложно понять правильно, и большую часть времени они не стоят хлопот ИМХО.
Примечание: я упростил некоторые вещи и пропустил детали, которые можно обнаружить только при использовании API проверки времени выполнения objc