我们在消息查找流程里面 ,经过了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));
}
}