8, iOS underlying analysis - Message forwarding mechanism

Message forwarding mechanism

 

View ways to help

command + right show Quick Help and then command + shift + 0

 

Messaging, Find

objc_msgSend , when the IMP approach did not seek to, first enter the dynamic method resolution, lookUpImpOrForward internal methods

IMP lookUpImpOrForward(Class cls, SEL sel, id inst, 
                       bool initialize, bool cache, bool resolver)
{
。。。。。。
    // No implementation found. Try method resolver once.

    if (resolver  &&  !triedResolver) {
        runtimeLock.unlock();
        _class_resolveMethod(cls, sel, inst);
        runtimeLock.lock();
        // Don't cache the result; we don't hold the lock so it may have 
        // changed already. Re-do the search from scratch instead.
        triedResolver = YES;
        goto retry;
    }
。。。。。。。
}

_class_resolveMethod   is our analytic method step, in internal methods, depending on whether the current class metaclass, a method to determine the currently executing class or object method is a method to resolve the next step, and returns a value as Bool

void _class_resolveMethod(Class cls, SEL sel, id inst)
{
    if (! cls->isMetaClass()) {
        // try [cls resolveInstanceMethod:sel]
        // 调用对象方法解析
        _class_resolveInstanceMethod(cls, sel, inst);
    } 
    else {
        // try [nonMetaClass resolveClassMethod:sel]
        // and [cls resolveInstanceMethod:sel]
      // 调用类方法解析
        _class_resolveClassMethod(cls, sel, inst);
        if (!lookUpImpOrNil(cls, sel, inst, 
                            NO/*initialize*/, YES/*cache*/, NO/*resolver*/)) 
        {
            _class_resolveInstanceMethod(cls, sel, inst);
        }
    }
}

Resolved within two methods, the principle is to transmit a current class  SEL_resolveInstanceMethod   or SEL_resolveClassMethod message (defined in both  objc-runtime.mm   file), and comments can be known by these two methods, in our NSObject root class has been implemented

SEL SEL_resolveInstanceMethod = NULL;// 解析实例方法
SEL SEL_resolveClassMethod = NULL;//解析类方法

+ (BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
+ (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

If both analytically and no treatment method can not be found by looking for, then the program will crash. If you do not want to crash, they can not find the case method, we can determine where the analytical method and assigned to this method IMP.

Because not find in the method when the system will automatically call these two methods ( resolveClassMethod   or   resolveInstanceMethod ), here to give the developers a chance to avoid the crash and fault tolerance, we need to rewrite the internal methods and  not find the corresponding realization the method   dynamically add an existing IMP

/***********************************************************************
* _class_resolveInstanceMethod
* Call +resolveInstanceMethod, looking for a method to be added to class cls.
* cls may be a metaclass or a non-meta class.
* Does not check if the method already exists.
调用+resolveInstanceMethod,寻找一个方法添加到类cls。
cls可以是元类,也可以是非元类。
*不检查方法是否已经存在。
**********************************************************************/
static void _class_resolveInstanceMethod(Class cls, SEL sel, id inst)
{
如果找到了返回
    if (! lookUpImpOrNil(cls->ISA(), SEL_resolveInstanceMethod, cls, 
                         NO/*initialize*/, YES/*cache*/, NO/*resolver*/)) 
    {
        // Resolver not implemented.
        return;
    }

    BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
    bool resolved = msg(cls, SEL_resolveInstanceMethod, sel);

    // Cache the result (good or bad) so the resolver doesn't fire next time.
    // +resolveInstanceMethod adds to self a.k.a. cls
    IMP imp = lookUpImpOrNil(cls, sel, inst, 
                             NO/*initialize*/, YES/*cache*/, NO/*resolver*/);

    。。。。一些判断打印
}

 

Message forwarding process

Forwarding method

oc method call by the underlying will objc_msgSend for message transmission

After the cache in order to quickly find imp, and a method to find the class list, if still not find the target method, then enter the message forwarding process

 

1), first find yourself

2) dynamic method resolution (sometimes special treatment, if they did not see the dynamic resolution process there is no treatment)

3), fast flow, others handle (if there is no special treatment to see if the treatment is carried over to someone else)

4) slow forwards (to others if there is no deal, the equivalent of a drift bottle, Who picked to deal with, they do not collapse on the line these methods will accumulate to the current - (void.) ForwardInvocation: (NSInvocation * ) anINvocation))

Method name: Mark _ routes _ affairs such as: lg_home_sayHello

 

1, dynamic method resolution

  1. Inside the class + (Bool) resolveInstanceMethod: (SEL) sel {return [super resolveInstanceMethod: sel]}
  2. Inside the class + (Bool) resolveClassMethod: (SEL) sel {class methods to the return [super resolveClassMethod: sel]}
  3. If the corresponding processing method (sel) in which dynamic resolution, then resolve ... to go only once, if not addressed, there will be in the lower to other processing, this method will go twice
  4. If you can not find a class method - dynamic method resolution
  5. Class - Yuan class - NSObject
    1. resolveClassMethod whether you're dealing with - as long as attention yuan class
    2. resolveClassMethod no treatment - resolveInstanceMethod
    3. The figure above, why then walked resolution method in class, but also to go to conduct a meta-class look? 1, for fault 2, to avoid duplicate names.
    4. lookUpImpOrForwrad (class cls, SEL sel ......) will go inside the processing method
    5. _class_resolveMethod(class cls, …….)

 

Dynamic Resolution supplement

Go to the normal search method

If you do not find the dynamic method resolution to go, to see if there is special treatment.

First determination is not pass into the metaclass, if metaclass is a class method.

If a specially treated (that is, to give him added a sel - imp), this time will return imp, and then again to find the imp

 

 

2, fast forward

  1. forwardingTargetForSelector
  2. Return parameter is an object, if this object is the message of non-nil, non-self, then the system will run forwarded to the object to perform. Otherwise, continue to look for other processes
  3. This system gave a SEL will be transferred to other objects opportunity
  4. If given object can not be achieved, it is a slower process forward

3, slow forward

  1. methodSignatureForSelector
  2. This function allows overloading party an opportunity to throw a signature function, and then from the back of the forwardInvocation: to do it.
  3. SEL return signature method, the signature is returned to the method according to the parameters of the package
  4. forwardInvocation
    1. Real implementation methodSignatureForSelector: NSMethodSignature returned. This function which can be NSInvocation forwarded multiple times to multiple objects, which is flexible in this way places. (ForwardingTargetForSelector only exclusive form of an object from the Selector)
    2. /Applications/xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework
      1. objc_msgSend Find imp cache
      2. Slow recursive
      3. 、、、、、、、、、、、、、、、
      4. Find You is not got special treatment
      5. Have you ever handled to others
      6. Do not mean do not want to deal with
        1. methodSignatureForSelector way of knowing, the underlying method signature is very important, I need to tell
        2. forwardInvocation: anInvocation have such interface provides a transaction manager, all transactions here
        3. I do not want to crash, if you want to deal with, and left on top of the interface to handle
      7. If you do not want to deal with that, I will not go doesNotRecognizeSelector

 

4, can not handle the error message

  1. Error message could not be processed
    1. doesNotRecognizeSelector
  2. flow chart
  3. problem
    1. Dynamic method resolution process will not come twice
    2. resolveClassMethod finish resolvenInstanceMethod
  4. other
    1. Disassembly, to give the corresponding pseudocode

to sum up:

Published 83 original articles · won praise 12 · views 180 000 +

Guess you like

Origin blog.csdn.net/shengdaVolleyball/article/details/104060042