概(fei)述(hua)
...(省略1024亿个byte)
探究
为了研究Objective-C
的消息转发,做了一系列测试
Test 0
- 内容: 调用对象存的方法
步骤:
定义一个
TestObject
类,继承NSObject
, 重写的方法如下:@implementation TestObject + (BOOL)resolveClassMethod:(SEL)sel { BOOL ret = [super resolveClassMethod:sel]; NSLog(@"-->> %@ %p resolveClassMethod: %@, return: %d", [self class], self, NSStringFromSelector(sel), ret); return ret; } - (BOOL)respondsToSelector:(SEL)aSelector { BOOL ret = [super respondsToSelector:aSelector]; NSLog(@"-->> %@ %p respondsToSelector: %@, return: %d", [self class], self, NSStringFromSelector(aSelector), ret); return ret; } - (id)forwardingTargetForSelector:(SEL)aSelector { id ret = [super forwardingTargetForSelector:aSelector]; NSLog(@"-->> %@ %p forwardingTargetForSelector: %@, return: %@", [self class], self, NSStringFromSelector(aSelector), ret); return ret; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodSignature* ret = [super methodSignatureForSelector:aSelector]; NSLog(@"-->> %@ %p methodSignatureForSelector: %@, return: %@", [self class], self, NSStringFromSelector(aSelector), ret); return ret; } - (void)forwardInvocation:(NSInvocation *)anInvocation { NSLog(@"-->> %@ %p forwardInvocation: %@", [self class], self, anInvocation); [super forwardInvocation:anInvocation]; } @end
代码
[[TestObject alloc] init];
- 结果: 什么都没有log
- 结论: 调用存在的方法, 没有发生任何消息转发
Test 1
- 内容: 调用对象不存在的方法
步骤:
代码
TestObject* obj = [[TestObject alloc] init]; [obj performSelector:NSSelectorFromString(@"not exists sel")];
- 结果:
TestObject
调用了forwardingTargetForSelector:
(返回nil), 然后调用methodSignatureForSelector:
(返回nil), 最后logunrecognized selector sent to instance
- 结论: 调用不存在的方法, 发生了消息转发
Test 2
- 内容:
TestObject_1
重写forwardingTargetForSelector:
(返回TestObject
对象), 调用它们都不存在的方法 步骤:
- 定义
TestObject_1
, 继承TestObject
@implementation TestObject_1 - (id)forwardingTargetForSelector:(SEL)aSelector { id ret = [[TestObject alloc] init]; NSLog(@"-->> %@ %p forwardingTargetForSelector: %@, return: %@", [self class], self, NSStringFromSelector(aSelector), ret); return ret; } @end
- 代码:
TestObject_2* obj = [[TestObject_2 alloc] init]; [obj performSelector:NSSelectorFromString(@"not exists sel")];
- 定义
- 结果:
TestObject_1
对象先调用了forwardingTargetForSelector:
(返回TestObject对象), 然后TestObject
对象调用forwardingTargetForSelector:
(返回nil), 跟着调用methodSignatureForSelector:
(返回nil), 最后logunrecognized selector sent to instance
- 结论: 不存在的方法转发到了其它对象处理失败
Test 3
- 内容:
TestObject_2
重写forwardingTargetForSelector:
(返回TestObject_1
), 调用TestObject_2
不存在, 但TestObject_1
存在的方法 步骤:
- 定义
TestObject_2
, 继承TestObject
@implementation TestObject_2 - (id)forwardingTargetForSelector:(SEL)aSelector { id ret = [[TestObject_1 alloc] init]; NSLog(@"-->> %@ %p forwardingTargetForSelector: %@, return: %@", [self class], self, NSStringFromSelector(aSelector), ret); return ret; } @end
- TestObject_1, 添加方法
- (void)testObject_1ExistsMethod { NSLog(@"-->> %@ %p I am exists", [self class], self); }
- 代码
TestObject_2* obj = [[TestObject_2 alloc] init]; [obj performSelector:NSSelectorFromString(@"testObject_1ExistsMethod")];
- 定义
- 结果:
TestObject_2
对象先调用了forwardingTargetForSelector:
(返回TestObject_1对象), 然后TestObject_1
对象调用了testObject_1ExistsMethod
- 结论: 不存在的方法转发到了其它对象处理成功
Test 4
- 内容:
TestObject_3
重写methodSignatureForSelector:
(不返回nil)和forwardInvocation:
, 调用不存在的方法 步骤:
- 定义
TestObject_3
, 继承TestObject
@implementation TestObject_3 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSLog(@"-->> %@ %p methodSignatureForSelector: %@", [self class], self, NSStringFromSelector(aSelector)); return [NSObject methodSignatureForSelector:@selector(init)]; } - (void)forwardInvocation:(NSInvocation *)anInvocation { NSLog(@"-->> %@ %p forwardInvocation: %@", [self class], self, anInvocation); // [super forwardInvocation:anInvocation]; // will crash, because the method signature is not right } @end
- 代码
TestObject_3* obj = [[TestObject_3 alloc] init]; [obj performSelector:NSSelectorFromString(@"not exists sel")];
- 定义
- 结果: 先调用了
forwardingTargetForSelector:
, 然后methodSignatureForSelector:
, 最后forwardInvocation:
, 没发生崩溃 - 结论:
TestObject_3
自己处理了不存在方法
总结
如下图
测试代码
TestMessageForwarding: https://github.com/skytoup/TestMessageForwarding