概(fei)述(hua)
…(省略1024亿个byte)
探究
为了研究Objective-C的消息转发,做了一系列测试
Test 0
- 内容: 调用对象存的方法
-
步骤:
-
定义一个
TestObject类,继承NSObject, 重写的方法如下:1234567891011121314151617181920212223242526272829303132
@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
- 内容: 调用对象不存在的方法
-
步骤:
-
代码
12
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, 继承TestObject123456789
@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, 继承TestObject123456789
@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
-
- (void)testObject_1ExistsMethod {
NSLog(@"-->> %@ %p I am exists", [self class], self);
}
- 结果:
TestObject_2对象先调用了forwardingTargetForSelector:(返回TestObject_1对象), 然后TestObject_1对象调用了testObject_1ExistsMethod - 结论: 不存在的方法转发到了其它对象处理成功
Test 4
- 内容:
TestObject_3重写methodSignatureForSelector:(不返回nil)和forwardInvocation:, 调用不存在的方法 -
步骤:
-
定义
TestObject_3, 继承TestObject12345678910111213
@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: github.com/skytoup/Tes…
本文为博主skytoup原创文章,未经博主skytoup允许不得转载。