Reputation: 1191
I'm trying to implement a Dynamic property in my project This is my code.
MyClass.h
@interface MyClass : UIView
@property (strong, nonatomic) NSString *name;
@end
MyClass.m
@implementation MyClass
@dynamic name;
-(void)setName:(NSString *)name{
self.name = name;
}
@end
But when I run my app has crashed.
When I use an ivar had this error.
Upvotes: 4
Views: 6716
Reputation: 6513
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:
@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.)@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
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
In practice, you would just use "autosynthetisation".
@interface MyClass : UIView
@property (strong, nonatomic) NSString *name;
@end
@implementation MyClass
@end
This means,
@synthesize
or @dynamic
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.
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
propertiesthey 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
Upvotes: 12
Reputation: 2595
This StackOverflow answer: https://stackoverflow.com/a/1160545/7833793 does a good job of explaining what the differences between @synthesize
and @dynamic
are. Typically you use @dynamic
if you're delegating the task of implementing the accessors (get, set). It seems to me like you would want to use @synthesize here. But with modern objective c, you shouldn't even need to specify and the iVar will be created for you automatically.
i.e.:
MyClass.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MyClass : NSObject
@property (strong, nonatomic) NSString *name;
@end
NS_ASSUME_NONNULL_END
MyClass.m
#import "MyClass.h"
@implementation MyClass
- (void)setName:(NSString *)name {
_name = name;
}
@end
Upvotes: 4
Reputation: 9672
Your solution leads to recursion, you are getting crash since you are not using ivar
in setter, try this instead:
-(void)setName:(NSString *)name{
_name = name;
}
Upvotes: 1