Can anyone give me clear picture about dynamic property and its usage? y not use the usual @property everywhere?
@dynamic thing;
is merely a way to inform the system not to generate getters/setters for the thing
, that you (or someone else) will provide them for you—As in, they'll be there at runtime.
This is in contrast to @synthesize
which tells the compiler to generate the getter/setter (as appropriate) for you.
@dynamic is (in my experience) used primarily in conjunction with Core Data and subclasses of NSManagedObject. To quote Marcus Zarra's Core Data,
By declaring them [attributes/relationships], we are telling the compiler to ignore any warnings associated with there properties because we "promise" to generate them at runtime. Naturally, if the turn up missing at runtime, then our application is going to crash.
Dynamic properties are used when you don't provide an implementation at compile time, but ensure that one exists at runtime. Being a dynamic language, Objective-C can respond to messages at runtime, even if the class doesn't have an implementation at compile time.
Here's a contrived example: Let's say you have a Book
class, backed by an NSMutableDictionary
that contains the keys title
and author
. However, you want Book
to respond to title
and author
as well, and have them as properties; title
and author
will grab the appropriate value from the dictionary, and setTitle:
and setAuthor:
will change the value stored in the dictionary. You could do so with this code:
#import <Foundation/Foundation.h>
@interface Book : NSObject
{
NSMutableDictionary *data;
}
@property (retain) NSString *title;
@property (retain) NSString *author;
@end
@implementation Book
@dynamic title, author;
- (id)init
{
if ((self = [super init])) {
data = [[NSMutableDictionary alloc] init];
[data setObject:@"Tom Sawyer" forKey:@"title"];
[data setObject:@"Mark Twain" forKey:@"author"];
}
return self;
}
- (void)dealloc
{
[data release];
[super dealloc];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
NSString *sel = NSStringFromSelector(selector);
if ([sel rangeOfString:@"set"].location == 0) {
return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
} else {
return [NSMethodSignature signatureWithObjCTypes:"@@:"];
}
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
NSString *key = NSStringFromSelector([invocation selector]);
if ([key rangeOfString:@"set"].location == 0) {
key = [[key substringWithRange:NSMakeRange(3, [key length]-4)] lowercaseString];
NSString *obj;
[invocation getArgument:&obj atIndex:2];
[data setObject:obj forKey:key];
} else {
NSString *obj = [data objectForKey:key];
[invocation setReturnValue:&obj];
}
}
@end
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Book *book = [[Book alloc] init];
printf("%s is written by %s\n", [book.title UTF8String], [book.author UTF8String]);
book.title = @"1984";
book.author = @"George Orwell";
printf("%s is written by %s\n", [book.title UTF8String], [book.author UTF8String]);
[book release];
[pool release];
return 0;
}
Note the the methods are "created" at runtime via forwardInvocation:
; hence, title
and author
are dynamic properties.
(This isn't the best example, but I think it gets the point across.)