OBJECTIVE-C 2.0 run-time programming

Source: Internet
Author: User

OBJECTIVE-C 2.0 's run-time environment called Morden Runtime,ios and Mac OS X 64-bit programs all run on
This environment, which means that the Mac OS X 32-bit program runs in the old OBJECTIVE-C 1.0 Runtime Environment legacy
runtime, here we only explain the Morden runtime.
The interaction with the runtime is mainly in three different places, namely the A.objective-c source code (for example, the category you define
is automatically added to the original class at run time, and the B.nsobject method (ismemberclassof
C. Run-time functions. Since the first two have been explained in the previous document, here we talk about the run-time letter
The relevant content of the number.
(1.) ISA pointer:
There is a member variable of class ISA pointer type in NSObject, because most of our objects are directly or indirectly from
NSObject inherits this ISA member variable, and ISA will point to the object's class object at run time.
All objects of a class have the same class object (as in JAVA), which guarantees that every class in memory
Types have a unique type description. This class object also has an Isa pointer that points to the class of the parent class at the previous level
Object.
After understanding this Isa, you can understand that at the time of inheritance, a extends B, you call A's method A (), the first
First Isa to a class object to find the A () method, found on the call, if not found, drive A's class
object to find in the class object of the parent class B.
(2.) SEL and Imp:
In the first document, we mentioned the method selector sel, which can be obtained in the following two ways:
(SEL) @selector (the name of the method)
(SEL) Nsselectorfromstring (string of the name of the method)

Alternatively, you can obtain the method name specified by the SEL by using the (nsstring*) nsstringfromselector (SEL) function.
String.

In fact, objective-c at compile time, according to each defined method's name, the parameter sequence, generates a only

Integer ID, which is the SEL. Therefore, the run-time lookup method is through this unique identity, and the
Not by the name of the method.

OBJECTIVE-C also provides the IMP type, IMP represents a pointer to the implementation method (function pointer), through which you can

To directly access an implementation method, thus avoiding the static call mode of [XXX message], which requires the first
method, and then through the IMP to find the specific implementation method, and finally send the message to bring about the efficiency of the implementation of the problem.
In general, if you call a method repeatedly in multiple loops, the IMP will send a message to the object directly
A little more efficient.


Cases:
PERSON.M:
#import "Person.h"
@implementation person
@synthesize name;
@synthesize weight;
-(person*) Initwithweight: (int) w{
Self=[super Init];
if (self) {
Weight=w;
}
return self;
}
-(void) Print: (nsstring*) str{
NSLog (@ "%@%@", str,name);
}
-(void) dealloc{
[Self setname:nil];
[Super Dealloc];
}
@end
MAIN.M:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * Pool = [[NSAutoreleasePool alloc] init]; Person *person=[[person alloc] initwithweight:68];
[Email protected] "Jetta";
SEL print_sel=nsselectorfromstring (@ "Print:");
IMP Imp=[person Methodforselector:print_sel];
Imp (person,print_sel,@ "*********");
[Pool drain];
return 0;
}
Here we see a pointer to imp, which can be obtained through the Methodforselector: (SEL) method in the NSObject
Ask this pointer function, we use IMP (id,sel,argument1,... ...), the first parameter is the object that invokes the method,
The two method is the selector object for the method, and the third parameter is a mutable parameter that represents the parameters required by the delivery method.
(3.) Objc_msgsend function:
With the explanation of the ISA pointer, we know that the method call in Objective-c is bound at run time, and then further
Look, the compiler will send the object message [xxx method] to Objc_msgsend (ID receiver,sel selector, parameters ...)
Function call. So the print method in the example above can also be called as follows:
Objc_msgsend (person,print_sel,@ "++++++++");
Of course, this is what the compiler is going to do, and when you write code, you don't need to use this notation directly.
With the explanation of Isa, SEL, IMP, actually the objc_msgsend call process should look like this:
A. First pass receiver of the first parameter, locate its ISA pointer, and then use it in the class object pointed to by Isa
The second parameter selector the method of finding;
B. If not found, use the new Isa pointer in the current class object to the class object of the parent class at the previous level
Find
C. When the method is found, the current object is found based on the self pointer in receiver, invoking the actual
The current method (IMP pointer function), and then pass the parameter, calling the implementation method.
D. If the NSObject class object has been found and no method is found for you to call, it will report that the sending
The error of the message.
(4.) Dynamic method parsing:
In the property accessors section of the new feature in Objective-c 2.0, we actually ignore the fact that a dynamic
Property. OBJECTIVE-C 2.0 adds the @dynamic directive, which represents the property accessor method of the variable, which is the dynamic real
Now, you need to inherit from the NSObject in the + (BOOL) Resolveinstancemethod: (SEL) Sel method specified in the
A method or function that is dynamically implemented.
Cases:
Person.h:
@interface person:nsobject{
NSString *name;
float weight;
} @property (Retain,readwrite) nsstring* name;
@property (readonly) float weight;
@property float height;-(person*) initwithweight: (int) weight;

-(void) Print: (nsstring*) str;
@end


PERSON.M:
void DynamicMethod (ID self,sel _cmd,float w) {
printf ("dynamicmethod-%s\n", [Nsstringfromselector (_cmd) cstringusingencoding:nsutf8stringencoding]);
printf ("%f\n", W);
}
@implementation person
@synthesize name;
@synthesize weight;
@dynamic height; Note here//The @dynamic directive is used in the implementation class


-(person*) Initwithweight: (int) w{
Self=[super Init];
if (self) {
Weight=w;
}
return self;
}
-(void) Print: (nsstring*) str{
NSLog (@ "%@%@", str,name);
}
+ (BOOL) Resolveinstancemethod: (SEL) sel{
NSString *methodname=nsstringfromselector (SEL);
BOOL Result=no;
See if we want to implement the method name dynamically
if ([MethodName isequaltostring:@ "setheight:"]) {
Class_addmethod ([Self class], SEL, (IMP) DynamicMethod, "[Email protected]:f");
Result=yes;
}
return result;
}
-(void) dealloc{
[Self setname:nil];
[Super Dealloc];
}
@end Here we use the @dynamic directive for the height of the interface in the implementation class, and then you need to specify a letter
Number or other class of methods as the setter of the height, the getter method run-time implementation. For simplicity, we specify
The functions defined in PERSON.M (note that this is a C-language function, not a objective-c method) DynamicMethod
The runtime implementation of the Setter method as the height. DynamicMethod parameters of a method that is specified as a dynamic implementation
Like the following requirements:
A. The first and second parameters must be ID, SEL;
B. At the beginning of the third parameter, you can define the parameters according to the original method (for example: setheight: (float)).
Next, you need to overwrite the NSObject class method Resolveinstancemethod, this method will need to dynamically
The selector of the implemented method (SetHeight:) is passed in, and we decide whether it is a selector that needs to be implemented dynamically,
If so, transfer the right of disposal to DynamicMethod. How to transfer it? We're going to use the run-time function here.
Class_addmethod (class,sel,imp,char[]).
Run-time functions are located in Objc/runtime.h, which, like names, are functions of the C language. Follow these functions
Different functions, mainly divided into the following categories: Operation type, Operation object, operation protocol, etc. Most of these functions can be
To see what it means by name, for example: Class_addprotocol dynamically adds protocols to a type at run time,
Objc_getprotocol converts a string into a protocol, and so on. What these run-time functions are all about, you can
See the Official Apple page:
http://developer.apple.com/library/ios/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#/ /apple_ref/doc/uid/tp40001418
To get back to the point, let's explain the Class_addmethod method needed here, which has four parameters,
The Class indicates which type you want to add the method to, and the SEL parameter represents the selector for the method you want to add, and IMP says you want to
Adds a function pointer to a concrete implementation of the method's runtime. In fact, here you can see that the SEL can't be found at runtime.
To the actual method to invoke, IMP can really find the implementation method.
Before explaining the fourth parameter char[], let's take a look at the @encode directive mentioned in the first document,
The @encode directive was used when the non-Objective-c object type was encapsulated as a nsvalue type, but we didn't
The meaning of this instruction is explained in detail. In fact @encode () can accept any type, objective-c
Makes a type code, which converts any type to a string, for example: The void type is encoded after V,
The image type is @,sel type: etc., specifically you can refer to the Apple official page for a description of type Encoding:
http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ Ocrttypeencodings.html#//apple_ref/doc/uid/tp40008048-ch100-sw
Now let's take a formal look at the following fourth parameter [email protected]:f meaning, which describes the description of the function that imp points to,
Following the @encode instruction compiled character description, the first character v means the return value is void, the remaining word identifier
The parameter description of the DynamicMethod function, @ means the first parameter ID, which is naturally the second parameter sel,f is
A third parameter, float. Since the first two parameters of the dynamic method implementation must be ID and SEL, the fourth
The second to third character of a string in the argument must be @:.
We see that the return value of the Resolveinstancemethod method is bool, which means that this method returns Yes to find
The concrete implementation of the dynamic method, otherwise it means that no real implementation is found at runtime, and the program reports the error.
With the above processing, the OBJECTIVE-C runtime only discovers that you have invoked the setter of the attributes of the @dynamic callout,
Getter method, it will automatically go to Resolveinstancemethod to find the real implementation. Which means you're
When calling Peson.height in main.m, the DynamicMethod function is actually called.
In fact, in addition to the properties of the @dynamic annotation, if you call a method that does not exist in the type, it will be
Resolveinstancemethod or Resolveclassmethod intercept, but because you do not deal with, so will report cannot
The error that identifies the message.
You may be lamenting that a @dynamic command is really troublesome to use, and I am also studying a half-day Apple official obscure
The birds of the bird understand. But fortunately, the general Objective-c run-time programming does not use much, unless you want to design a
Dynamic functions, such as: Download an upgrade package from the network, do not need to exit the original program, you can dynamically
Replace the old functions and other similar requirements.
(5.) Message Forwarding:
At the end of the previous objc_msgsend () function, we summarize the Objective-c method invocation process, in the final step
We say that if we find the way down or we don't find the calling method, we're going to report an error, actually there's a detail, that
That is, the system calls-(void) forwardinvocation when the calling method is eventually not found: (nsinvocation*)
Invocation method, if your object does not implement this method, call NSObject's Forwardinvocation party
Law, the error that does not recognize the message, is actually nsobject Forwardinvocation thrown out of the exception.
We are here to tell you the internal implementation process of this system, is actually to tell you that you can overwrite forwardinvocation
method to change the nsobject of the throw exception. For example, you can forward a message that cannot be processed to B
To deal with.
Nsinvocation is an object that contains receiver, selector, which includes sending a message to an object
All elements: Object, method name, parameter sequence, you can call Nsinvocation's Invoke method to send this message
Activated.
Cases:
MAIN.M:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * Pool = [[NSAutoreleasePool alloc] init];
Person *person=[[person alloc] init];
[Email protected] "Jetta";
[Person fly];
[Person release];
[Pool drain];
return 0;
}
Here we call a method that does not exist in the person fly.
BIRD.M:
#import "Bird.h"
@implementation Bird
-(void) fly{
printf ("Bird Can fly!");
}
@end
Person.m
@implementation person
@synthesize name;
@synthesize weight;
-(nsmethodsignature*) Methodsignatureforselector: (SEL) selector{
The method of calling the parent class first
Nsmethodsignature *signature=
[Super Methodsignatureforselector:selector];
If the current object cannot respond to this selector, then the method signature of the selector construct must be nil
if (!signature) {
First determine if the bird instance has the ability to respond to this selector
if ([Bird Instancesrespondtoselector:selector]) {
Gets the method signature object of the bird selector
Signature=[bird Instancemethodsignatureforselector:selector];
}
}
return signature;
}
-(void) Forwardinvocation: (nsinvocation*) invocation{
First verify that Bird has the ability to respond to the selector contained in the invocation
if ([Bird instancesrespondtoselector:[invocation selector]]) {
Create an instance of the right to transfer message response bird
Bird *bird=[bird New];
Activates the message in invocation, but the message's responder is bird, not the default self.
[Invocation Invokewithtarget:bird];
}
}
-(void) dealloc{
[Self setname:nil];
[Super Dealloc];
}
@end let's analyze it in detail if you want to forward a message that cannot be processed to another object, which several
Step: A. First, you want to overwrite the Methodsignatureforselector method in NSObject. This is because if you want to eliminate
Transfer from person to bird processing, you must sign the Fly method of the person included in the Nsinvocation
A method signature that converts the fly to bird, which is to correct the method signature.
As a result, you also see the creation of nsinvocation, the internal use of two objects, one is receiver, one is
Nsmethodsignature, and Nsmethodsignature is created by the SEL. Nsinvocation does exist a class-side
Method Invocationwithmethodsignature returns an instance of itself.
B. Then we cover the Forwardinvocation method, not using the Invoke method, but the Invokewithtarget method,
This means that the call is transferred from self to bird.
In fact, the message forwarding mechanism can not only be used to deal with errors found in methods, you can also implement multiple inheritance in disguise. False
If our person wants to have all the features of bird and Fish, you can actually call it with the person's instance.
Bird, Fish method, as long as in person's forwardinvocation, the message of the response to Bird or
Examples of Fish are available. But this is a bit of a BT, unless it is a last resort, don't do it,
But you can also see from here objective-c how flexible and powerful this language is, which Java is completely
Can be compared to the.

OBJECTIVE-C 2.0 run-time programming

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.