GitHub参考
PS:参考GitHub分享的objc-runtime-master
代码,及Runtime005
代码
runtime源码中消息转发相关代码
// No implementation found, and method resolver didn't help.
// Use forwarding.
imp = (IMP)_objc_msgForward_impcache;
cache_fill(cls, sel, imp, inst);
_objc_msgForward_impcache
这个方法又进入到汇编语言中,我们查看真机arm64环境下的汇编语言
STATIC_ENTRY __objc_msgForward_impcache
MESSENGER_START
nop
MESSENGER_END_SLOW
// No stret specialization.
b __objc_msgForward
END_ENTRY __objc_msgForward_impcache
ENTRY __objc_msgForward
adrp x17, __objc_forward_handler@PAGE
ldr x17, [x17, __objc_forward_handler@PAGEOFF]
br x17
END_ENTRY __objc_msgForward
查找_objc_forward_handler
我们觉得上面的报错信息莫名的熟悉,没错,就是在调用的方法未实现的时候,系统抛出的错误信息
找到这里,我们发现代码并没有开源,怎么实现的我们无法知道。
但是,我们可以通过extern void instrumentObjcMessageSends(BOOL)
API打印来查看
#import <Foundation/Foundation.h>
#import "TZPerson.h"
//声明C语言的方法后,才可以调用
extern void instrumentObjcMessageSends(BOOL);
int main(int argc, const char * argv[]) {
@autoreleasepool {
instrumentObjcMessageSends(YES);
[[TZPerson new] walk];
instrumentObjcMessageSends(NO);
}
return 0;
}
结果会输出到/private/tmp/msgSend-XXX
文件路径下
使用终端打开文件
cd /private/tmp
open msgSends-2188
查看文件内容
+ TZPerson NSObject initialize
+ TZPerson NSObject new
- TZPerson NSObject init
//动态方法解析
+ TZPerson NSObject resolveInstanceMethod:
+ TZPerson NSObject resolveInstanceMethod:
//消息转发
- TZPerson NSObject forwardingTargetForSelector:
- TZPerson NSObject forwardingTargetForSelector:
//方法名注册
- TZPerson NSObject methodSignatureForSelector:
- TZPerson NSObject methodSignatureForSelector:
- TZPerson NSObject class
- TZPerson NSObject doesNotRecognizeSelector:
- TZPerson NSObject doesNotRecognizeSelector:
- TZPerson 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:
+ NSException NSObject initialize
+ NSException NSException exceptionWithName:reason:userInfo:
+ NSException NSObject alloc
- NSException NSException initWithName:reason:userInfo:
- __NSCFConstantString NSObject copy
- __NSCFConstantString __NSCFConstantString copyWithZone:
- __NSCFString NSObject copy
- __NSCFString __NSCFString copyWithZone:
- NSException NSObject autorelease
+ NSException NSObject self
- NSException NSObject isKindOfClass:
- NSException NSObject isKindOfClass:
- NSException NSObject class
+ NSMutableDictionary NSObject new
+ NSMutableDictionary NSObject alloc
+ NSMutableDictionary NSDictionary allocWithZone:
+ NSDictionary NSObject self
+ NSMutableDictionary NSObject self
+ __NSPlaceholderDictionary __NSPlaceholderDictionary mutablePlaceholder
- __NSPlaceholderDictionary __NSPlaceholderDictionary init
- __NSPlaceholderDictionary __NSPlaceholderDictionary initWithCapacity:
+ __NSDictionaryM __NSDictionaryM __new:::::
+ NSThread NSThread callStackReturnAddresses
+ _NSCallStackArray NSObject initialize
+ _NSCallStackArray _NSCallStackArray arrayWithFrames:count:symbols:
+ _NSCallStackArray NSObject new
+ _NSCallStackArray NSObject alloc
+ _NSCallStackArray NSArray allocWithZone:
+ NSArray NSObject self
+ NSMutableArray NSObject self
+ NSObject NSObject allocWithZone:
- _NSCallStackArray NSObject init
- _NSCallStackArray NSObject autorelease
+ NSThread NSThread callStackSymbols
+ _NSCallStackArray _NSCallStackArray arrayWithFrames:count:symbols:
+ _NSCallStackArray NSObject new
+ _NSCallStackArray NSObject alloc
+ _NSCallStackArray NSArray allocWithZone:
+ NSArray NSObject self
+ NSMutableArray NSObject self
+ NSObject NSObject allocWithZone:
- _NSCallStackArray NSObject init
- _NSCallStackArray NSObject autorelease
- __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 self
- 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 NSValue initialize
+ NSValue NSObject class
+ NSNumber NSNumber initialize
+ NSNumber NSObject class
+ NSPlaceholderValue NSNumber initialize
+ NSNumber NSObject class
+ NSPlaceholderValue NSObject self
+ NSPlaceholderNumber NSNumber initialize
+ NSNumber NSObject class
+ NSPlaceholderNumber NSObject self
+ 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
- _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 string
+ NSMutableString NSMutableString allocWithZone:
- 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:
- __NSCFString NSObject autorelease
- _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
- __NSCFString NSString description
- __NSCFString NSString description
- _NSCallStackArray NSArray countByEnumeratingWithState:objects:count:
- __NSCFString NSObject autorelease
- __NSCFString __NSCFString UTF8String
- NSMutableString NSString UTF8String
- __NSCFString __NSCFString length
- __NSCFString NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
- __NSCFString __NSCFString length
+ NSMutableData NSMutableData dataWithLength:
+ NSMutableData NSMutableData allocWithZone:
+ NSMutableData NSObject self
+ NSConcreteMutableData NSObject initialize
- NSConcreteMutableData NSConcreteMutableData initWithLength:
- NSConcreteMutableData NSConcreteMutableData setLength:
- NSConcreteMutableData NSObject autorelease
- NSConcreteMutableData NSConcreteMutableData mutableBytes
- __NSCFString NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
- __NSCFString __NSCFString length
- __NSCFString __NSCFString UTF8String
- __NSCFConstantString __NSCFString _fastCStringContents:
- __NSCFString NSObject isProxy
- __NSCFString NSObject respondsToSelector:
- __NSCFString NSObject class
- __NSCFString __NSCFString isNSString__
- __NSCFString NSObject isNSCFConstantString__
- __NSCFString __NSCFString _fastCStringContents:
我们实现forwardingTargetForSelector
方法
#import "TZPerson.h"
#import "TZDog.h"
#import <objc/runtime.h>
@implementation TZPerson
- (id) forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(walk)) {
//消息转发到其他对象中
return [TZDog new];
}
return [super forwardingTargetForSelector:aSelector];
}
@end
执行OK
2018-11-19 14:52:53.793666+0800 Runtime001[2221:149865] -[TZDog walk]
Program ended with exit code: 0
也可以通过方法名注册的方式进行转发
#import "TZPerson.h"
#import "TZDog.h"
#import <objc/runtime.h>
@implementation TZPerson
/// 方法名注册
- (NSMethodSignature* ) methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(walk)) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
- (void) forwardInvocation:(NSInvocation *)anInvocation {
// NSLog(@"%s", __func__);
// 转到其他类
// [anInvocation invokeWithTarget:[TZDog new]];
/// 转发给自己
anInvocation.selector = @selector(run);
// anI
[anInvocation invoke];
}
- (void) run {
NSLog(@"%s", __func__);
}
@end
类方法消息转发
参考GitHubRuntime006
代码
#import <Foundation/Foundation.h>
@interface TZPerson : NSObject
+ (void) walk;
@end
#import <Foundation/Foundation.h>
#import "TZPerson.h"
extern void instrumentObjcMessageSends(BOOL);
int main(int argc, const char * argv[]) {
@autoreleasepool {
instrumentObjcMessageSends(YES);
[TZPerson walk];
instrumentObjcMessageSends(NO);
}
return 0;
}
运行查看
+ TZPerson NSObject initialize
+ TZPerson NSObject resolveClassMethod:
+ TZPerson NSObject resolveClassMethod:
+ NSObject NSObject resolveInstanceMethod:
+ NSObject NSObject resolveInstanceMethod:
+ TZPerson NSObject forwardingTargetForSelector:
+ TZPerson NSObject forwardingTargetForSelector:
+ TZPerson NSObject methodSignatureForSelector:
+ TZPerson NSObject methodSignatureForSelector:
+ TZPerson NSObject doesNotRecognizeSelector:
+ TZPerson NSObject doesNotRecognizeSelector:
+ TZPerson 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:
+ NSException NSObject initialize
+ NSException NSException exceptionWithName:reason:userInfo:
+ NSException NSObject alloc
- NSException NSException initWithName:reason:userInfo:
- __NSCFConstantString NSObject copy
- __NSCFConstantString __NSCFConstantString copyWithZone:
- __NSCFString NSObject copy
- __NSCFString __NSCFString copyWithZone:
- NSException NSObject autorelease
+ NSException NSObject self
- NSException NSObject isKindOfClass:
- NSException NSObject isKindOfClass:
- NSException NSObject class
+ NSMutableDictionary NSObject new
+ NSMutableDictionary NSObject alloc
+ NSMutableDictionary NSDictionary allocWithZone:
+ NSDictionary NSObject self
+ NSMutableDictionary NSObject self
+ __NSPlaceholderDictionary __NSPlaceholderDictionary mutablePlaceholder
- __NSPlaceholderDictionary __NSPlaceholderDictionary init
- __NSPlaceholderDictionary __NSPlaceholderDictionary initWithCapacity:
+ __NSDictionaryM __NSDictionaryM __new:::::
+ NSThread NSThread callStackReturnAddresses
+ _NSCallStackArray NSObject initialize
+ _NSCallStackArray _NSCallStackArray arrayWithFrames:count:symbols:
+ _NSCallStackArray NSObject new
+ _NSCallStackArray NSObject alloc
+ _NSCallStackArray NSArray allocWithZone:
+ NSArray NSObject self
+ NSMutableArray NSObject self
+ NSObject NSObject allocWithZone:
- _NSCallStackArray NSObject init
- _NSCallStackArray NSObject autorelease
+ NSThread NSThread callStackSymbols
+ _NSCallStackArray _NSCallStackArray arrayWithFrames:count:symbols:
+ _NSCallStackArray NSObject new
+ _NSCallStackArray NSObject alloc
+ _NSCallStackArray NSArray allocWithZone:
+ NSArray NSObject self
+ NSMutableArray NSObject self
+ NSObject NSObject allocWithZone:
- _NSCallStackArray NSObject init
- _NSCallStackArray NSObject autorelease
- __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 self
- 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 NSValue initialize
+ NSValue NSObject class
+ NSNumber NSNumber initialize
+ NSNumber NSObject class
+ NSPlaceholderValue NSNumber initialize
+ NSNumber NSObject class
+ NSPlaceholderValue NSObject self
+ NSPlaceholderNumber NSNumber initialize
+ NSNumber NSObject class
+ NSPlaceholderNumber NSObject self
+ 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
- _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 string
+ NSMutableString NSMutableString allocWithZone:
- 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:
- __NSCFString NSObject autorelease
- _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
- __NSCFString NSString description
- __NSCFString NSString description
- _NSCallStackArray NSArray countByEnumeratingWithState:objects:count:
- __NSCFString NSObject autorelease
- __NSCFString __NSCFString UTF8String
- NSMutableString NSString UTF8String
- __NSCFString __NSCFString length
- __NSCFString NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
- __NSCFString __NSCFString length
+ NSMutableData NSMutableData dataWithLength:
+ NSMutableData NSMutableData allocWithZone:
+ NSMutableData NSObject self
+ NSConcreteMutableData NSObject initialize
- NSConcreteMutableData NSConcreteMutableData initWithLength:
- NSConcreteMutableData NSConcreteMutableData setLength:
- NSConcreteMutableData NSObject autorelease
- NSConcreteMutableData NSConcreteMutableData mutableBytes
- __NSCFString NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
- __NSCFString __NSCFString length
- __NSCFString __NSCFString UTF8String
- __NSCFConstantString __NSCFString _fastCStringContents:
- __NSCFString NSObject isProxy
- __NSCFString NSObject respondsToSelector:
- __NSCFString NSObject class
- __NSCFString __NSCFString isNSString__
- __NSCFString NSObject isNSCFConstantString__
- __NSCFString __NSCFString _fastCStringContents:
#import "TZDog.h"
@implementation TZDog
+ (void) walk {
NSLog(@"%s", __func__);
}
- (void) run {
NSLog(@"%s", __func__);
}
@end
#import "TZPerson.h"
#import "TZDog.h"
#import <objc/runtime.h>
@implementation TZPerson
+ (id) forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(walk)) {
return [TZDog class];
}
return [super forwardingTargetForSelector:aSelector];
}
@end
执行结果
2018-11-19 15:26:06.218900+0800 Runtime001[2592:168326] +[TZDog walk]
Program ended with exit code: 0
也可以转发到类的实例方法中
#import "TZPerson.h"
#import "TZDog.h"
#import <objc/runtime.h>
@implementation TZPerson
// 方法名注册
+ (NSMethodSignature* ) methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(walk)) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
+ (void) forwardInvocation:(NSInvocation *)anInvocation {
//NSLog(@"%s", __func__);
[anInvocation invokeWithTarget:[TZDog new]];
/// 转发给自己
// anInvocation.selector = @selector(run);
// anInvocation.target = self;
// [anInvocation invoke];
}
+ (void) run {
NSLog(@"%s", __func__);
}
@end
#import "TZDog.h"
@implementation TZDog
- (void) walk {
NSLog(@"%s", __func__);
}
@end