一、NSProxy 简介
NSProxy 是一个抽象类,它实现了protocol NSObject 所要求的基本方法,譬如内省相关的isKindOfClass:派发消息相关的performSelector 系列相关方法等;但是不能直接使用它创建对象。
子类化NSProxy 的要求也很简单,实现-forwardInvocation: 和-methodSignatureForSelector: 这两个方法即可,显然,这两个方法与消息转发相关,实现这两个方法的典型姿势是:
- (void)forwardInvocation:(NSInvocation *)anInvocation {
[anInvocation invokeWithTarget:_realObject]; // _realObject是自定义的实例变量
}
– (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [_realObject methodSignatureForSelector:aSelector];
}
二、NSProxy 的消息转发机制
虽然NSProxy 和 class NSObject 都定义了 -forwardInvocation: 和 -methodSignatureForSelector, 但这两个方法并没有在protocol NSObject 中声明;两者对这两个方法的调用逻辑完全不同。
对于Class NSObject 而言,接收到消息后先去自身的方法列表里找匹配的 selector,如果找不到,会沿着继承体系去 superclass 的方法列表找;如果还找不到,先后会经过+resolveInstanceMethod:和-forwardingTargetForSelector:处理,处理失败后,才会到-methodSignatureForSelector:/-forwardInvocation:进行最后的挣扎。
但对于NSProxy,接收 unknown selector 后,直接回调-methodSignatureForSelector:/-forwardInvocation:,消息转发过程比class NSObject要简单得多。
三、-init
除了上述的-methodSignatureForSelector:和-forwardInvocation:,NSProxy另外两个方法也非常值得说一说。
首先是-init。事实上,NSProxy没有定义这个方法,对于直接继承NSProxy的类,创建对象时不需要使用[super init]之类的调用进行初始化。为啥 Apple 不为NSProxy提供默认的构造器呢?我想这和它的定位有关吧,它是一个抽象类,不提供默认的-init反而能进一步阻止用户直接使用NSProxy创建对象。
四、NSProxy 优势
用NSProxy设计代理类的优势
NSProxy会将自省相关方法直接 forward 到forwardInvocation:回调,如果基于class NSObject实现类似的效果,得另外写不少代码,比较麻烦。
NSProxy比class NSObject干净得多,后者各种 category(譬如NSObject(NSKeyValueCoding))定义了诸多方法,这些方法的存在使得消息转发变得更麻烦,因为得区分class NSObject对象本身和其所指向的 realObject。