Transfer from http://blog.csdn.net/haishu_zheng/article/details/12873151
The @dynamic in Objective-c
The difference between @dynamic and @synthesize
@property have two corresponding words, one is @synthesize and the other is @dynamic. If @synthesize and @dynamic are not written, then the default is @syntheszie var = _var;
The semantics of @synthesize is that if you do not implement setter methods and Getter methods manually, then the compiler will automatically add these two methods to you.
@dynamic tells the compiler that the setter and getter methods of the property are implemented by the user themselves and are not generated automatically. (Of course, for ReadOnly properties, only getter is required). If a property is declared as @dynamic var, then you do not provide the @setter method and the @getter method, the compile time is not a problem, but when the program runs to Instance.var =somevar, due to the lack of setter method will cause the program to crash , or when running to Somevar = Var, the lack of getter method can also cause a crash. Compile-time is no problem, the runtime executes the corresponding method, which is called dynamic binding.
Second, through the private variables to achieve @dynamic access method
1) Book.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface Book:nsobject
{
@private
__strong NSString *_name;
__strong NSString *_author;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *author;
@property (nonatomic, copy) nsstring*version;
@end
2) BOOK.M
#import "Book.h"
@implementation Book
@dynamic name;
@dynamicauthor;
@synthesizeversion = _version;
-(ID) init
{
self = [super init];
if (self)
{
}
return self;
}
-(NSString *) name
{
if (nil = = _name)
{
_name = @ "You forgot Inputbook name";
}
return _name;
}
-(void) SetName: (NSString *) name
{
_name = name;
NSLog (@ "_name address:%p", _name);
}
-(NSString *) author
{
if (nil = = _author)
{
_author = @ "You forgot Inputbook author";
}
return _author;
}
-(void) Setauthor: (NSString *) author
{
_author = author;
}
@end
As you can see from the code above, with @dynamic, you can access a private variable in the access method to assign a value or to take a value. @synthesize uses @synthesize var = _var directly to equate attributes with private variables. This is the difference between the two in the writing form.
Third, through the message forwarding to realize the @dynamic access method
If you use @dynamic var = _var for an attribute, the compiler immediately errors. You won't be able to use _var like @synthesize in the setter method and getter method of Var, but you can't write the setter method and getter method as follows.
-(void) SetVar: (ID) Newvar
{
Self.var =newvar;
}
-(void) var
{
return Self.var;
}
Both of these methods call themselves, causing an infinite loop that directly causes the program to crash.
A setter and getter method using message forwarding mechanism to implement @dynamic is provided here.
First on the code:
1) Book.h
#import <Foundation/Foundation.h>
@interface Book:nsobject
{
@private
Nsmutabledictionary *_propertiesdict;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) Nsstring*author;
@property (nonatomic, copy) nsstring*version;
@end
2) BOOK.M
#import "Book.h"
@implementation Book
@dynamic name; cannot be written as name = _name, otherwise the compiler will immediately error
@dynamic author;
@synthesizeversion;
-(ID) init
{
self = [super init];
if (self)
{
_propertiesdict = [[Nsmutabledictionary alloc] init];
}
return self;
}
-(Nsmethodsignature *) Methodsignatureforselector: (SEL) Selector
{
NSString *sel = nsstringfromselector (selector);
if ([Sel rangeofstring:@ "set"].location = = 0)
{
return [nsmethodsignature signaturewithobjctypes: "[email protected]:@"];
}
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:&objatindex:2];
[_propertiesdict setobject:obj Forkey:key];
}
Else
{
NSString *obj = [_propertiesdict Objectforkey:key];
[Invocation setreturnvalue:&obj];
}
}
@end
3) main.m
#import <Foundation/Foundation.h>
#import "Book.h"
int main (int argc, const char * argv[])
{
@autoreleasepool
{
Book *book = [[Book alloc] init];
Book.name = @ "C + + primer";
Book.author = @ "Stanley B.lippman";
Book.version = @ "5.0";
NSLog (@ "%@", book.name);
NSLog (@ "%@", Book.author);
NSLog (@ "%@", book.version);
}
return 0;
}
Program Analysis:
1) before adding a message forwarding function to a program, you must overwrite two methods, namely Methodsignatureforselector: and Forwardinvocation:. Methodsignatureforselector: The effect of creating a valid method signature for a message implemented by another class. Forwardinvocation: Forwards the selector to an object that actually implements the message.
2) The methods in Objective-c are hidden by default for two parameters: Self and _cmd. Self points to the object itself, and _cmd points to the method itself. Give two examples to illustrate:
Example one:-(NSString *) name
This method actually has two parameters: Self and _cmd.
Example two:-(void) SetValue: (int) Val
This method actually has three parameters: Self, _cmd, and Val.
The parameter type of a method that is specified as a dynamic implementation is as follows:
A. The first parameter type must be an ID (that is, the type of self)
B. The second parameter type must be SEL (that is, the _cmd type)
C. From the third parameter, you can define it according to the parameter type of the original method. Give two examples to illustrate:
Example one: setheight: (cgfloat) The parameter height in height is floating-point, so the third parameter type is F.
Example two: Again, for example setname: (NSString *) The parameter name in name is a string type, so the third parameter type is @
3) in main.m a code is Book.name = @ "C + + Primer", when the program runs here, it will go to book.m to find SetName: This assignment method. However, BOOK.M does not have this method, so the program enters the Methodsignatureforselector: in the message forwarding. After execution, return with "[Email protected]:@" As the method signature type.
Here [email protected]:@ what is it? In fact, the first character v here means that the return type of the function is void, followed by the explanation in the three character reference above 2) to know, respectively, is self, _cmd, name, the type ID of the three parameter, SEL, NSString.
Then the program enters the Forwardinvocation method. The resulting key is the method name SetName: And then using [invocationgetargument:&objatindex:2]; to get to the parameter value, here is "C + + primer". Why is the index here to take 2? As previously analyzed, the No. 0 parameter is self, the 1th parameter is _cmd, and the 2nd parameter is the one with the back of the method.
Finally, a variable dictionary is used to assign values. This completes the entire setter process.
4) in MAIN.M There is a code is NSLOG (@ "%@", Book.name), and when the program runs here, it will go to BOOK.M to find the name of the value method. However, BOOK.M does not have this method of value, so the program into the Methodsignatureforselector: in the message forwarding. After execution, return with "@@:" As the method signature type. Here the first character @ represents the function return type NSString, the second character @ represents the type ID of self, and the third character: the type SEL that represents _cmd.
Then the program enters the Forwardinvocation method. The resulting key is the method name. Finally, the corresponding value is obtained from the dictionary according to this key, so the whole getter process is completed.
5) Note that the process of debugging the code, we find only the assignment and value of name and author into Methodsignatureforselector: and forwardinvocation: These two methods. There is also an assignment and value for the property version, and does not enter Methodsignatureforselector: and forwardinvocation: These two methods. This is because the Version property is identified as @synthesize, and the compiler automatically adds the Setversion and version two methods, so there is no message forwarding.
Iv. use of @dynamic in Nsmanagedobject subclasses
The most common use of @dynamic is in Nsmanagedobject, where programming setters and getter methods are not required. The reason: @dynamic tell the compiler not to do the processing, so that the compilation through, its getter and setter method will be dynamically created at run time, by the core data framework for such properties to generate access methods.
@dynamic in Objective-c (ext.)