必备知识架构-①语言-消息转发2
一、NSProxy
NSProxy,你可以通过继承它,并重写它的以下两个方法以实现消息转发到另一个实例。说白了,NSProxy专为代理而生(负责将消息转发到真正的target的代理类)。从类名来看是代理类,专门负责代理对象转发消息的。相比NSObject类来说NSProxy更轻量级,通过NSProxy可以帮助Objective-C间接的实现多重继承的功能。
1 | - (void)forwardInvocation:(NSInvocation *)anInvocation; |
1、通过NSProxy可以帮助Objective-C间接的实现多重继承的功能的例子
现在比较流行的说法是用它来模拟多重继承,大致过程就是让它Hold住/包含你要实现多继承的类的对象,然后被hold住的对象的行为定义在接口中,并让Proxy去实现这些接口。然后再转发的时候把消息转发到实现了该接口的对象去执行,这样就好像实现了多重继承一样。注意:这个真不是多重继承,只是包含,然后把消息路由到指定的对象而已,其实完全可以用NSObject类来实现。
天使=人+鸟
1 | Person *person = [Person new]; |
另一个例子:NSProxy的学习使用
1 | // AngelProxy.h |
2、NSProxy 和 NSObject 的比较
相比NSObject,NSProxy更轻量级,做消息转发效率更高。
NSObject寻找方法顺序:本类->(父类-)>(动态方法解析)-> 消息转发;
NSproxy顺序:本类->消息转发
3、NSProxy的用途
AOP面向切片编程
iOS中面向切片编程一般有两种方式 ,一个是直接基于runtime 的method-Swizzling.还有一种就是基于NSProxy
解决NSTimer, CADisplayLink等强引用target引起的无法释放问题。如NSTimer:利用消息转发来断开NSTimer对象与视图之间的强引用关系。初始化NSTimer时把触发事件的target替换成一个单独的对象,然后这个对象中NSTimer的SEL方法触发时让这个方法在当前的视图self中实现。
1
2
3
4self.timer = [NSTimer timerWithTimeInterval:1 target:self.proxy
selector:@selector(timerEvent) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
// 这里我们timer的target使用AYProxy对象,它会实现你这个timer想要实现的timerEvent消息转发给self。从而避免了循环引用协议类代码为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#import
@interface AYProxy : NSProxy
@property (nonatomic, weak) id obj;
@end
#import "AYProxy.h"
@implementation AYProxy
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSMethodSignature *sig = nil;
sig = [self.obj methodSignatureForSelector:aSelector];
return sig;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
[anInvocation invokeWithTarget:self.obj];
}
@end多重继承
实现类似CAAnimation类族.