A property is just a bundle of two methods: a getter and a setter. So, when you write
@property (strong, nonatomic) NSString *name;
what you are really saying is
- (NSString *)name;
- (void)setName:(NSString *)name;
After that, each time the compiler encounters an expression of the form obj.name
, it translates it to [obj name]
. And each time you see a statement like obj.name = @"hello";
, the compiler translates it to [obj setName:@"hello"]
.
The next thing is you have to make sure the property behaves properly. You have many options:
- Write getters and setters manually, referring to an iVar
- Synthesize getter and setter
- Autosynthesize getter and setter
- Write custom getters and setters
- Use
@dynamic
to avoid compile time warnings, because you intend to do runtime magic. (Really, that's not what you want to do, because you need to understand the basics first.)
Write getters and setters manually, referring to an iVar
@interface MyClass : UIView {
NSString *_name;
}
@property (strong, nonatomic) NSString *name;
@end
and in the implementation
@implementation MyClass
- (NSString *)name {
return _name;
}
- (void)setName:(NSString *)name {
_name = name;
}
@end
Synthesize getter and setter
The last section is basically equivalent to this
@interface MyClass : UIView {
NSString *_name;
}
@property (strong, nonatomic) NSString *name;
@end
@implementation MyClass
@synthesize name = _name;
@end
Autosynthesize getter and setter
In practice, you would just use "autosynthetisation".
@interface MyClass : UIView
@property (strong, nonatomic) NSString *name;
@end
@implementation MyClass
@end
This means,
- if you just declare a property
- don't call
@synthesize
or @dynamic
- don't implement any custom getter and setter
the code above will just create an iVar named _name
and a getter and setter that looks exactly like the one in the first example.
This means that the the first two and this sections are equivalent, because they produce the same code.
Write custom getters and setters
This is what the term "dynamic property" really means. For example, you may want the name to be always uppercase. So you may write a property like this.
@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
(in the code above, I changed strong
to copy
- don't worry, this is just a comment anyways. And it's a true one, because the uppercaseString
will never be the same, it will always be a copy of the original.)
This is maybe the only really interesting case! For example, this kind of property is what UIKit uses all the time, e.g. the text
property of UILabel
is a dynamic property like that. It doesn't just set some iVar, but it also makes sure that the visible text on the screen changes too.
@dynamic
properties
they are really tricky to get right, and most of the time they are not worth the hassle IMHO.
Note: I simplified some things and left out details which are only detectable when using objc runtime inspection APIs