iOS进阶—Runtime源码解析:消息转发

GitHub参考
PS:参考GitHub分享的objc-runtime-master代码,及Runtime005代码

iOS进阶—目录


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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值