Objective-c Runtime (RPM)

Source: Internet
Author: User


Objective-c


Objective-c extends the C language and joins the object-oriented and Smalltalk messaging mechanisms. The core of this extension is a runtime library written in C and compiled languages. It is the cornerstone of Objective-c object-oriented and dynamic mechanism.



Objective-c is a dynamic language, which means that it requires not only a compiler, but also a runtime system to dynamically create classes and objects, deliver messages, and forward them. Understanding Objective-c's Runtime mechanism can help us understand the language better, expand the language when appropriate, and address some design or technical issues in the project from a system level. To understand the Runtime, first understand its core-message passing (Messaging).


Message Delivery (Messaging)

I ' m sorry that I long ago coined the term "objects" for this topic because it gets many people to focus on the lesser idea . The big idea is "messaging" –that are what the kernal[sic] of Smalltalk are all about ... The key in making great and growable systems are much more to design how it modules communicate rather than what their int Ernal properties and behaviors should be.


Alan Kay has repeatedly stressed that the core of Smalltalk is not object-oriented, object-oriented is just the lesser ideas, message delivery is the big idea.



In many languages, such as C, invoking a method is actually jumping to a point in memory and starting to execute a piece of code. There is no dynamic feature, because this is determined at compile time. In Objective-c, however, the[object foo]syntax does not immediately execute the code of the Foo method. It is a message that sends an object called Foo at run time. This message, which may be handled by object, may be forwarded to another object, or it can be ignored to pretend that the message was confiscated. Many different messages can also be implemented with the same method. These are all determined when the program is running.



In fact, the syntax of the OBJECTIVE-C function call you write at compile time will be translated into a C function callobjc_msgSend(). For example, the following two lines of code are equivalent:


 
 
[array insertObject:foo atIndex:5];

objc_msgSend(array, @selector(insertObject:atIndex:), foo, 5);


The key to messaging is hidden inobjc_objectthe ISA pointer andobjc_classin the class dispatch table.


objc_object,objc_classAndOjbc_method


In Objective-c, classes, objects, and methods are a struct of C, and from theobjc/objc.hheader file we can find their definition:


 
struct objc_object {  
    Class isa  OBJC_ISA_AVAILABILITY;
};

struct objc_class {  
    Class isa  OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
    Class super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    **struct objc_method_list **methodLists**;
    **struct objc_cache *cache**;
    struct objc_protocol_list *protocols;
#endif
};

struct objc_method_list {  
    struct objc_method_list *obsolete;
    int method_count;

#ifdef __LP64__
    int space;
#endif

    /* variable length structure */
    struct objc_method method_list[1];
};

struct objc_method {  
    SEL method_name;
    char *method_types;    /* a string representing argument/return types */
    IMP method_imp;
};


objc_method_listThe essence is anobjc_methodarray of variable lengths with elements. Aobjc_methodstruct has a function name, the SEL, a string that represents the type of the function (see Type Encoding), and the implementation of the function Imp.



From these definitions, you can see that sending a message alsoobjc_msgSenddoes something.objc_msgSend(obj, foo)for this example:


    1. First, the ISA pointer of obj finds its class;
    2. Find Foo in the class method list;
    3. If the class does not reach Foo, continue to look for it in the superclass;
    4. Once the function of Foo is found, it executes its implementation imp.


But there is a problem with this implementation, which is inefficient. But a class often has only 20% of functions that are often called, which can account for 80% of the total number of calls. It is not reasonable for each message to traverse onceobjc_method_list. If you cache a function that is often called, it can greatly improve the efficiency of the function query. This is whatobjc_classanother important memberobjc_cachedoes--after finding Foo,method_namesave Foo as key asmethod_impvalue. When you receive the Foo message again, you can find it directly in the cache and avoid traversing itobjc_method_list.


Dynamic method parsing and forwarding


In the example above,foowhat happens if you don't find it? Typically, the program hangs up at run time and throws an unrecognized selector sent to ... exception. But before the exception is thrown, the Objective-c runtime will give you three chance to save the program:


    1. Method resolution
    2. Fast forwarding
    3. Normal forwarding
Method Resolution


First, the OBJECTIVE-C runtime invokes+resolveInstanceMethod:or gives+resolveClassMethod:you the opportunity to provide a function implementation. If you add a function and return YES, the runtime restarts the message sending process.fooas an example, you can do this:


 
void fooMethod(id obj, SEL _cmd)  
{
    NSLog(@"Doing foo");
}

+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
    if(aSEL == @selector(foo:)){
        class_addMethod([self class], aSEL, (IMP)fooMethod, "[email protected]:");
        return YES;
    }
    return [super resolveInstanceMethod];
}


Core Data is useful to this approach. The getter and setter of the properties in Nsmanagedobjects is dynamically added at run time.



If the Resolve method returns NO, the runtime moves to the next step: Message Forwarding (msg Forwarding).



Ps:ios 4.3 Adds a lot of new runtime methods, mostly with IMP prefixes, such asimp_implementationWithBlock()quickly creating a imp with block.
The above example can be rewritten as:


IMP fooIMP = imp_implementationWithBlock(^(id _self) {  
    NSLog(@"Doing foo");
});

class_addMethod([self class], aSEL, fooIMP, "[email protected]:");
Fast forwarding


If the target object is implemented-forwardingTargetForSelector:, Runtime calls this method, giving you the chance to forward the message to other objects.


- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if(aSelector == @selector(foo:)){
        return alternateObject;
    }
    return [super forwardingTargetForSelector:aSelector];
}


As long as this method returns not nil and self, the entire message sending process is restarted and of course the sent object becomes the object you return. Otherwise, you will continue to Normal fowarding.



This is called Fast, just to differentiate the next forwarding mechanism. Because this step does not create any new objects, the next forwarding creates a Nsinvocation object, so it is relatively faster.


Normal forwarding


This step is the last time the Runtime gives you a chance to save. First it sends-methodSignatureForSelector:a message to get the function's arguments and return value types. If-methodSignatureForSelector:nil is returned, the Runtime sends-doesNotRecognizeSelector:a message, and the program is then hung out. If a function signature is returned, Runtime creates a Nsinvocation object and sends a-forwardInvocation:message to the target object.



Nsinvocation is actually a description of a message, including information such as selector and parameters. So you can-forwardInvocation:change the incoming Nsinvocation object in, then send-invokeWithTarget:a message to it, and pass in a new target:


- (void)forwardInvocation:(NSInvocation *)invocation
{
    SEL sel = invocation.selector; if([alternateObject respondsToSelector:sel]) {
        [invocation invokeWithTarget:alternateObject];
    } else {
        [self doesNotRecognizeSelector:sel];
    }
}


Many places in Cocoa have used messaging mechanisms to extend language, such as Proxies, Nsundomanager, and Responder Chain. Nsproxy is designed to be used as a proxy for forwarding messages, Nsundomanager intercepts a message and sends it, and Responder Chain guarantees that a message is forwarded to the appropriate responder.


Summarize


Sending a message to an object in Objective-c follows several steps:


    1. Try to find the message in the dispatch table of the object class. If found, jump to the corresponding function imp to execute the implementation code;
    2. If not found, Runtime will send+resolveInstanceMethod:or+resolveClassMethod:try to resolve the message;
    3. If the Resolve method returns No,runtime, send-forwardingTargetForSelector:allows you to forward the message to another object;
    4. If no new target object is returned, Runtime sends-methodSignatureForSelector:and-forwardInvocation:messages. You can send a-invokeWithTarget:message to forward the message manually or send a-doesNotRecognizeSelector:throw exception.


Using the Objective-c runtime feature, we can expand our language to address some of the design and technical issues in project development. In the next article, I will introduce method swizzling technology and how to use method swizzling to do Logging.


Reference


Message forwarding



Objective-c-messaging



The Faster Objc_msgsend



Understanding OBJECTIVE-C Runtime



Objective-c Runtime (RPM)


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.