iOS 消息转发流程

我们在消息查找流程里面 ,经过了cache的快速查找和methodlist的慢速查找都找不到方法后:那么,在 lookUpImpOrForward里面就来到

1.方法动态决议 resolveInstanceMethod 

// No implementation found. Try method resolver once.



    if (slowpath(behavior & LOOKUP_RESOLVER)) {

        behavior ^= LOOKUP_RESOLVER;//^操作控制只进来一次

        return resolveMethod_locked(inst, sel, cls, behavior);

    }



static NEVER_INLINE IMP

resolveMethod_locked(id inst, SEL sel, Class cls, int behavior)
{//来到这里 那就是没有这个方法了 就是imp 为nil  直接崩溃 or给机会拯救

    runtimeLock.assertLocked();

    ASSERT(cls->isRealized());



    runtimeLock.unlock();

//判断是否为元类 

    if (! cls->isMetaClass()) {//不是元类 那么就是对象方法动态决议

        // try [cls resolveInstanceMethod:sel]

        resolveInstanceMethod(inst, sel, cls);

    } 
 else {//是元类 那么就是类方法动态决议

        // try [nonMetaClass resolveClassMethod:sel]

        // and [cls resolveInstanceMethod:sel]

        resolveClassMethod(inst, sel, cls);

        if (!lookUpImpOrNilTryCache(inst, sel, cls)) {

            resolveInstanceMethod(inst, sel, cls);

        }

    }
// chances are that calling the resolver have populated the cache

    // so attempt using it

    return lookUpImpOrForwardTryCache(inst, sel, cls, behavior); // ??? 又查找一次 ? 是的 因为上面给了函数 可以动态添加方法 程序员可能会添加方法 所以我们再查一次

}


   

1.1 对象方法动态协议

static void resolveInstanceMethod(id inst, SEL sel, Class cls)

{

    runtimeLock.assertUnlocked();

    ASSERT(cls->isRealized());

    SEL resolve_sel = @selector(resolveInstanceMethod:);



    if (!lookUpImpOrNilTryCache(cls, resolve_sel, cls->ISA(/*authenticated*/true))) {

        // Resolver not implemented.

        return;

    }


BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;

    bool resolved = msg(cls, resolve_sel, 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 = lookUpImpOrNilTryCache(inst, sel, cls);

if (resolved  &&  PrintResolving) {

        if (imp) {

            _objc_inform("RESOLVE: method %c[%s %s] "

                         "dynamically resolved to %p", 

                         cls->isMetaClass() ? '+' : '-', 

                         cls->nameForLogging(), sel_getName(sel), imp);

        }

  else {

            // Method resolver didn't add anything?

            _objc_inform("RESOLVE: +[%s resolveInstanceMethod:%s] returned YES"

                         ", but no new implementation of %c[%s %s] was found",

                         cls->nameForLogging(), sel_getName(sel), 

                         cls->isMetaClass() ? '+' : '-', 

                         cls->nameForLogging(), sel_getName(sel));

        }

    }

}


   
         

1.1.1 动态决议添加方法

+ (BOOL)resolveInstanceMethod:(SEL)sel{

     // 处理 sel -> imp

    if (sel == @selector(查找方法名)) {

        IMP newImp     = class_getMethodImplementation(self, @selector(添加的方法名));

        Method method    = class_getInstanceMethod(self, @selector(添加的方法名));

        const char *type = method_getTypeEncoding(method);

        return class_addMethod(self, sel, newImp, type);

    }

    return [super resolveInstanceMethod:sel];

}

1.2 类方法动态决议

在resolveMethod_locked里面判断如果不是元类走的是对象方法动态决议;那么是元类的话那就走类方法的动态决议

// try [nonMetaClass resolveClassMethod:sel]

        // and [cls resolveInstanceMethod:sel]

        resolveClassMethod(inst, sel, cls);

        if (!lookUpImpOrNilTryCache(inst, sel, cls)) {

            resolveInstanceMethod(inst, sel, cls);

        }



就是进入resolveClassMethod 过程跟前面实例方法的大同小异

static void resolveClassMethod(id inst, SEL sel, Class cls)
{
    runtimeLock.assertUnlocked();
    ASSERT(cls->isRealized());
    ASSERT(cls->isMetaClass());

    if (!lookUpImpOrNilTryCache(inst, @selector(resolveClassMethod:), cls)) {
        // Resolver not implemented.
        return;
    }

    Class nonmeta;
    {
        mutex_locker_t lock(runtimeLock);
        nonmeta = getMaybeUnrealizedNonMetaClass(cls, inst);
        // +initialize path should have realized nonmeta already
        if (!nonmeta->isRealized()) {
            _objc_fatal("nonmeta class %s (%p) unexpectedly not realized",
                        nonmeta->nameForLogging(), nonmeta);
        }
    }
    BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
    bool resolved = msg(nonmeta, @selector(resolveClassMethod:), sel);

    // Cache the result (good or bad) so the resolver doesn't fire next time.
    // +resolveClassMethod adds to self->ISA() a.k.a. cls
    IMP imp = lookUpImpOrNilTryCache(inst, sel, cls);
    if (resolved  &&  PrintResolving) {
        if (imp) {
            _objc_inform("RESOLVE: method %c[%s %s] "
                         "dynamically resolved to %p", 
                         cls->isMetaClass() ? '+' : '-', 
                         cls->nameForLogging(), sel_getName(sel), imp);
        }
        else {
            // Method resolver didn't add anything?
            _objc_inform("RESOLVE: +[%s resolveClassMethod:%s] returned YES"
                         ", but no new implementation of %c[%s %s] was found",
                         cls->nameForLogging(), sel_getName(sel), 
                         cls->isMetaClass() ? '+' : '-', 
                         cls->nameForLogging(), sel_getName(sel));
        }
    }
}

1.2.1动态决议添加类方法

// 元类的以对象方法的方法
+ (BOOL)resolveClassMethod:(SEL)sel{
   
    NSLog(@"resolveClassMethod :%@-%@",self,NSStringFromSelector(sel));
    
    if (sel == @selector(方法名)) {
        IMP newImp     = class_getMethodImplementation(objc_getMetaClass("类名"), @selector(新方法));
        Method method    = class_getInstanceMethod(objc_getMetaClass("类名"), @selector(新方法));
        const char *type = method_getTypeEncoding(method);
        return class_addMethod(objc_getMetaClass("类名"), sel, newImp, type);
    }

    return [super resolveClassMethod:sel];
}

回到 resolveMethod_locked函数 我们发现 即便走了 resolveClassMethod 后面还是会走 resolveInstanceMethod;为什么呢?因为如果是类方法是添加在元类里面的 所以走resolveClassMethod是天经地义的事情;但是在isa的走位图里面,我们知道nsobject的元类可以指向nsobject,所以 如果我们在nsobject的分类里面添加resolveInstanceMethod来实现方法,也是可以给元类的继承链找到的。那么得到结论其实不管实例方法 和类方法的动态决议,我们都可以写在一个nsobject的分类里面通过实现resolveInstanceMethod来完成。

2.方法快速转发流程

 在lookUpImpOrForward里面方法动态决议后,我们发现可以走到 goto done; 

 done:
    if (fastpath((behavior & LOOKUP_NOCACHE) == 0)) {
#if CONFIG_USE_PREOPT_CACHES
        while (cls->cache.isConstantOptimizedCache(/* strict */true)) {
            cls = cls->cache.preoptFallbackClass();
        }
#endif
        log_and_fill_cache(cls, imp, sel, inst, curClass);
    }

那么log_and_fill_cache做了什么呢?

static void
log_and_fill_cache(Class cls, IMP imp, SEL sel, id receiver, Class implementer)
{
#if SUPPORT_MESSAGE_LOGGING
    if (slowpath(objcMsgLogEnabled && implementer)) {

//这个会打印一些什么信息呢? 怎么样才能让代码跑这里呢?  implementer必然存在 那么只有objcMsgLogEnabled值为真即可进来 那么全局搜索objcMsgLogEnabled 发现在instrumentObjcMessageSends可以设置它的值

        bool cacheIt = logMessageSend(implementer->isMetaClass(), 
                                      cls->nameForLogging(),
                                      implementer->nameForLogging(), 
                                      sel);
        if (!cacheIt) return;
    }
#endif
    cls->cache.insert(sel, imp, receiver);
}

logMessageSend会打印一些什么信息呢? 怎么样才能让代码跑这里呢?  implementer必然存在 那么只有objcMsgLogEnabled值为真即可进来 那么全局搜索objcMsgLogEnabled 发现在instrumentObjcMessageSends可以设置它的值

所以我们创建一个工程在里面调用一个没有实现的方法

   LGPerson *person = [LGPerson alloc];

    instrumentObjcMessageSends(YES);

     [person sayHello];

    instrumentObjcMessageSends(NO);

执行完后 可以查看log日志 (在logMessageSend里面有 snprintf (buf, sizeof(buf), "/tmp/msgSends-%d", (int) getpid ());)

所以我们只有打开tmp文件目录看是否有msgSends-xxx的文件即可 我进入后找到打开显示

+ LGPerson LGPerson resolveInstanceMethod:
+ LGPerson LGPerson resolveInstanceMethod:
+ NSString NSObject alloc
+ NSString NSString allocWithZone:
+ NSPlaceholderString NSString initialize
+ NSString NSObject class
- NSPlaceholderString NSPlaceholderString initWithBytesNoCopy:length:encoding:freeWhenDone:
- OS_xpc_serializer OS_xpc_object dealloc
- OS_object NSObject dealloc
+ OS_xpc_payload NSObject class
- OS_xpc_payload OS_xpc_payload dealloc
- NSObject NSObject dealloc
- OS_dispatch_mach_msg OS_dispatch_object dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
+ OS_xpc_mach_send NSObject initialize
- OS_xpc_mach_send OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
+ OS_xpc_uuid NSObject initialize
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_mach_send OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_serializer OS_xpc_object dealloc
- OS_object NSObject dealloc
+ OS_xpc_payload NSObject class
- OS_xpc_payload OS_xpc_payload dealloc
- NSObject NSObject dealloc
- OS_dispatch_mach_msg OS_dispatch_object dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_xpc_mach_send OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_mach_send OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_bundle OS_xpc_object dealloc
- OS_object NSObject dealloc
- __NSCFConstantString __NSCFString _fastCStringContents:
- NSTaggedPointerString NSObject isProxy
- NSTaggedPointerString NSObject respondsToSelector:
- NSTaggedPointerString NSObject class
+ NSTaggedPointerString NSObject resolveInstanceMethod:
+ NSTaggedPointerString NSObject resolveInstanceMethod:
- NSTaggedPointerString NSTaggedPointerString isNSString__
- NSTaggedPointerString NSObject isNSCFConstantString__
- NSTaggedPointerString NSTaggedPointerString _fastCStringContents:
- NSTaggedPointerString NSObject isProxy
- NSTaggedPointerString NSObject isNSObject__
- NSTaggedPointerString NSString description
- NSTaggedPointerString NSTaggedPointerString length
- NSTaggedPointerString NSTaggedPointerString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
- NSString NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
- NSTaggedPointerString NSTaggedPointerString length
- NSTaggedPointerString NSTaggedPointerString _fastCharacterContents
- NSTaggedPointerString NSTaggedPointerString _fastCharacterContents
- NSTaggedPointerString NSTaggedPointerString getCharacters:range:
- OS_xpc_serializer OS_xpc_object dealloc
- OS_object NSObject dealloc
+ OS_xpc_payload NSObject class
- OS_xpc_payload OS_xpc_payload dealloc
- NSObject NSObject dealloc
- OS_dispatch_mach_msg OS_dispatch_object dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_xpc_mach_send OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_mach_send OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
- OS_dispatch_data NSObject retain
- OS_dispatch_data NSObject release
- OS_dispatch_mach_msg OS_dispatch_object dealloc
- OS_xpc_serializer OS_xpc_object dealloc
- OS_dispatch_mach_msg OS_dispatch_object dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_data OS_xpc_object dealloc
- OS_dispatch_data NSObject release
- OS_dispatch_data OS_dispatch_data dealloc
+ NSData NSObject initialize
+ _NSDispatchData NSObject initialize
- _NSDispatchData NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
+ NSObject NSObject resolveInstanceMethod:
- LGPerson NSObject forwardingTargetForSelector:
- LGPerson NSObject forwardingTargetForSelector:
- LGPerson NSObject methodSignatureForSelector:
- LGPerson NSObject methodSignatureForSelector:
- LGPerson NSObject class
+ LGPerson LGPerson resolveInstanceMethod:
+ LGPerson LGPerson resolveInstanceMethod:
+ NSString NSObject alloc
+ NSString NSString allocWithZone:
- NSPlaceholderString NSPlaceholderString initWithBytesNoCopy:length:encoding:freeWhenDone:
- __NSCFConstantString __NSCFString _fastCStringContents:
- NSTaggedPointerString NSObject isProxy
- NSTaggedPointerString NSObject respondsToSelector:
- NSTaggedPointerString NSObject class
- NSTaggedPointerString NSTaggedPointerString isNSString__
- NSTaggedPointerString NSObject isNSCFConstantString__
- NSTaggedPointerString NSTaggedPointerString _fastCStringContents:
- NSTaggedPointerString NSObject isProxy
- NSTaggedPointerString NSObject isNSObject__
- NSTaggedPointerString NSString description
- NSTaggedPointerString NSTaggedPointerString length
- NSTaggedPointerString NSTaggedPointerString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
- NSString NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
- NSTaggedPointerString NSTaggedPointerString length
- NSTaggedPointerString NSTaggedPointerString _fastCharacterContents
- NSTaggedPointerString NSTaggedPointerString _fastCharacterContents
- NSTaggedPointerString NSTaggedPointerString getCharacters:range:
- OS_dispatch_data NSObject retain
- OS_dispatch_data NSObject release
- OS_xpc_serializer OS_xpc_object dealloc
- OS_dispatch_mach_msg OS_dispatch_object dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_data OS_xpc_object dealloc
- OS_dispatch_data NSObject release
- OS_dispatch_data OS_dispatch_data dealloc
- _NSDispatchData NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
+ NSObject NSObject resolveInstanceMethod:
- LGPerson NSObject doesNotRecognizeSelector:
- LGPerson NSObject doesNotRecognizeSelector:
- LGPerson NSObject class
- __NSCFConstantString __NSCFString _fastCStringContents:
- __NSCFString NSObject isProxy
- __NSCFString NSObject respondsToSelector:
- __NSCFString NSObject class
+ __NSCFString NSObject resolveInstanceMethod:
+ __NSCFString NSObject resolveInstanceMethod:
- __NSCFString __NSCFString isNSString__
- __NSCFString NSObject isNSCFConstantString__
- __NSCFString __NSCFString _fastCStringContents:
- OS_dispatch_data NSObject retain
- OS_dispatch_data NSObject release
- OS_dispatch_data NSObject retain
- OS_dispatch_data NSObject release
- OS_xpc_serializer OS_xpc_object dealloc
- OS_dispatch_mach_msg OS_dispatch_object dealloc
- OS_object NSObject dealloc
- OS_xpc_dictionary OS_xpc_object dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_data OS_xpc_object dealloc
- OS_dispatch_data NSObject release
- OS_dispatch_data OS_dispatch_data dealloc
- _NSDispatchData NSObject dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_uuid OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_string OS_xpc_object dealloc
- OS_object NSObject dealloc
+ OS_xpc_uint64 NSObject initialize
- OS_xpc_uint64 OS_xpc_object dealloc
- OS_object NSObject dealloc
- OS_xpc_data OS_xpc_object dealloc
- OS_dispatch_data NSObject release
- OS_dispatch_data OS_dispatch_data dealloc
- _NSDispatchData NSObject dealloc
- OS_object NSObject dealloc
- OS_object NSObject dealloc
+ NSException NSObject initialize
+ NSException NSException exceptionWithName:reason:userInfo:
- NSException NSException initWithName:reason:userInfo:
- __NSCFConstantString __NSCFConstantString copy
- __NSCFString __NSCFString copy
- NSException NSObject isKindOfClass:
- NSException NSObject isKindOfClass:
- NSException NSObject class
+ NSMutableDictionary NSObject new
+ NSMutableDictionary NSObject alloc
+ NSMutableDictionary NSDictionary allocWithZone:
- __NSPlaceholderDictionary __NSPlaceholderDictionary init
- __NSPlaceholderDictionary __NSPlaceholderDictionary initWithCapacity:
+ __NSDictionaryM NSObject self
- NSException NSException userInfo
+ NSThread NSThread callStackReturnAddresses
+ _NSCallStackArray NSObject initialize
+ _NSCallStackArray _NSCallStackArray arrayWithFrames:count:symbols:
+ _NSCallStackArray NSObject new
+ _NSCallStackArray NSObject alloc
+ _NSCallStackArray NSArray allocWithZone:
+ NSObject NSObject allocWithZone:
- _NSCallStackArray NSObject init
+ NSThread NSThread callStackSymbols
+ _NSCallStackArray _NSCallStackArray arrayWithFrames:count:symbols:
+ _NSCallStackArray NSObject new
+ _NSCallStackArray NSObject alloc
+ _NSCallStackArray NSArray allocWithZone:
+ NSObject NSObject allocWithZone:
- _NSCallStackArray NSObject init
- __NSDictionaryM __NSDictionaryM setObject:forKey:
- __NSCFConstantString __NSCFString hash
- __NSCFConstantString __NSCFConstantString copyWithZone:
- __NSDictionaryM __NSDictionaryM setObject:forKey:
- __NSCFConstantString __NSCFString hash
- __NSCFConstantString __NSCFConstantString copyWithZone:
- NSException NSObject retain
- NSException NSObject isKindOfClass:
- NSException NSObject isKindOfClass:
- NSException NSObject class
- NSException NSException name
- __NSCFConstantString __NSCFConstantString retain
- __NSCFConstantString __NSCFConstantString autorelease
- NSException NSException reason
- __NSCFString __NSCFString retain
- __NSCFString NSObject autorelease
- __NSDictionaryM __NSDictionaryM objectForKey:
- __NSCFConstantString __NSCFString hash
- _NSCallStackArray _NSCallStackArray count
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSValue NSObject initialize
+ NSNumber NSNumber initialize
+ NSNumber NSObject class
+ NSNumber NSNumber numberWithUnsignedInteger:
+ __NSCFNumber NSNumber initialize
+ NSNumber NSObject class
- __NSCFNumber __NSCFNumber unsignedIntegerValue
- __NSCFNumber __NSCFNumber unsignedLongValue
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSNumber NSNumber numberWithUnsignedInteger:
- __NSCFNumber __NSCFNumber unsignedIntegerValue
- __NSCFNumber __NSCFNumber unsignedLongValue
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSNumber NSNumber numberWithUnsignedInteger:
- __NSCFNumber __NSCFNumber unsignedIntegerValue
- __NSCFNumber __NSCFNumber unsignedLongValue
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSNumber NSNumber numberWithUnsignedInteger:
- __NSCFNumber __NSCFNumber unsignedIntegerValue
- __NSCFNumber __NSCFNumber unsignedLongValue
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSNumber NSNumber numberWithUnsignedInteger:
- __NSCFNumber __NSCFNumber unsignedIntegerValue
- __NSCFNumber __NSCFNumber unsignedLongValue
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSNumber NSNumber numberWithUnsignedInteger:
- __NSCFNumber __NSCFNumber unsignedIntegerValue
- __NSCFNumber __NSCFNumber unsignedLongValue
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSNumber NSNumber numberWithUnsignedInteger:
- __NSCFNumber __NSCFNumber unsignedIntegerValue
- __NSCFNumber __NSCFNumber unsignedLongValue
- __NSDictionaryM __NSDictionaryM objectForKey:
- __NSCFConstantString __NSCFString hash
- _NSCallStackArray NSArray description
- _NSCallStackArray _NSCallStackArray descriptionWithLocale:indent:
+ NSMutableString NSString initialize
+ NSString NSObject class
+ NSMutableString NSString string
+ NSMutableString NSMutableString allocWithZone:
+ NSPlaceholderMutableString NSString initialize
+ NSString NSObject class
- NSPlaceholderMutableString NSPlaceholderMutableString init
- __NSCFString NSObject autorelease
- __NSCFString __NSCFString appendString:
- __NSCFString __NSCFString appendFormat:
- __NSCFString __NSCFString appendFormat:
- __NSCFString __NSCFString appendFormat:
- __NSCFString __NSCFString appendFormat:
- __NSCFString __NSCFString appendFormat:
- __NSCFString __NSCFString appendFormat:
- __NSCFString __NSCFString appendFormat:
- __NSCFString __NSCFString appendString:
- _NSCallStackArray NSArray componentsJoinedByString:
- __NSCFConstantString __NSCFString isNSString__
- _NSCallStackArray _NSCallStackArray count
- _NSCallStackArray NSArray countByEnumeratingWithState:objects:count:
- _NSCallStackArray _NSCallStackArray count
- _NSCallStackArray NSArray getObjects:range:
- _NSCallStackArray _NSCallStackArray count
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSString NSString stringWithUTF8String:
+ NSString NSString allocWithZone:
- NSPlaceholderString NSPlaceholderString initWithBytes:length:encoding:
- __NSCFString NSObject autorelease
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSString NSString stringWithUTF8String:
+ NSString NSString allocWithZone:
- NSPlaceholderString NSPlaceholderString initWithBytes:length:encoding:
- __NSCFString NSObject autorelease
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSString NSString stringWithUTF8String:
+ NSString NSString allocWithZone:
- NSPlaceholderString NSPlaceholderString initWithBytes:length:encoding:
- __NSCFString NSObject autorelease
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSString NSString stringWithUTF8String:
+ NSString NSString allocWithZone:
- NSPlaceholderString NSPlaceholderString initWithBytes:length:encoding:
- __NSCFString NSObject autorelease
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSString NSString stringWithUTF8String:
+ NSString NSString allocWithZone:
- NSPlaceholderString NSPlaceholderString initWithBytes:length:encoding:
- __NSCFString NSObject autorelease
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSString NSString stringWithUTF8String:
+ NSString NSString allocWithZone:
- NSPlaceholderString NSPlaceholderString initWithBytes:length:encoding:
- _NSCallStackArray _NSCallStackArray objectAtIndex:
+ NSString NSString stringWithUTF8String:
+ NSString NSString allocWithZone:
- NSPlaceholderString NSPlaceholderString initWithBytes:length:encoding:
- __NSCFString NSObject autorelease
- __NSCFString NSString description
- __NSCFString NSString description
- __NSCFString NSString description
- __NSCFString NSString description
- __NSCFString NSString description

可以看到 在动态决议后还走了两个方法

+ NSObject NSObject resolveInstanceMethod:
- LGPerson NSObject forwardingTargetForSelector:
- LGPerson NSObject forwardingTargetForSelector:
- LGPerson NSObject methodSignatureForSelector:
- LGPerson NSObject methodSignatureForSelector:

2.1 快速转发流程 forwardingTargetForSelector

 当我们实现forwardingTargetForSelector的时候 可以给它指定一个有可以实现方法的对象即可

- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));

    objClass *obj = [[objClass alloc] init];//这个objClass 有实现当前没有找到的方法
    return obj;
}

2.2慢速转发流程 methodSignatureForSelector

- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
    return nil;
}
 慢速转发
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
    if (aSelector == @selector(sayHello)) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    }
    return [super methodSignatureForSelector:aSelector];
}



//
- (void)forwardInvocation:(NSInvocation *)anInvocation{
//    NSLog(@"%@ - %@",anInvocation.target,NSStringFromSelector(anInvocation.selector));
    LGStudent *s = [LGStudent alloc];
    if ([self respondsToSelector:anInvocation.selector]) {
        [anInvocation invoke];
    }else if ([s respondsToSelector:anInvocation.selector]){
        [anInvocation invokeWithTarget:s];
    }else{
        NSLog(@"%s - %@",__func__,NSStringFromSelector(anInvocation.selector));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值