使用NSProxy和NSObject设计代理类的差异
来源:互联网 发布:线割编程软件哪个好 编辑:程序博客网 时间:2024/06/06 14:00
转自:http://www.tanhao.me/code/160702.html/?utm_source=tuicool&utm_medium=referral
如有侵犯,请来信oiken@qq.com
经常发现在一些需要使用消息转发而创建代理类时, 不同的程序员都有着不同的使用方法, 有些采用继承于NSObject, 而有一些采用继承自NSProxy. 二者都是Foundation框架中的基类, 并且都实现了<NSObject>
这个接口, 从命名和文档中看NSProxy天生就是用来干这个事情的. 但即便如此, 它们却都定义了相同的消息转发的接口, 那我们在使用二者来完成这个工作时有什么差异呢.
先贴一下通过二者来创建代理类的最基本实现代码.
继承自NSProxy
1234567891011121314151617181920
@interface THProxyA : NSProxy@property (nonatomic, strong) id target;@end@implementation THProxyA- (id)initWithObject:(id)object { self.target = object; return self;}- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { return [self.target methodSignatureForSelector:selector];}- (void)forwardInvocation:(NSInvocation *)invocation { [invocation invokeWithTarget:self.target];}@end
继承自NSObject
1234567891011121314151617181920212223
@interface THProxyB : NSObject@property (nonatomic, strong) id target;@end@implementation THProxyB- (id)initWithObject:(id)object { self = [super init]; if (self) { self.target = object; } return self;}- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { return [self.target methodSignatureForSelector:selector];}- (void)forwardInvocation:(NSInvocation *)invocation { [invocation invokeWithTarget:self.target];}@end
代码基本是一致的, 除了初始化时规范的写法有细节差异, 这个差异是因为NSProxy这个基类没有定义默认的init方法.
1.经测试发现以下两个在<NSObject>
中定义的接口, 在二者之间表现是不一致的:
123456789
NSString *string = @"test";THProxyA *proxyA = [[THProxyA alloc] initWithObject:string];THProxyB *proxyB = [[THProxyB alloc] initWithObject:string];NSLog(@"%d", [proxyA respondsToSelector:@selector(length)]);NSLog(@"%d", [proxyB respondsToSelector:@selector(length)]);NSLog(@"%d", [proxyA isKindOfClass:[NSString class]]);NSLog(@"%d", [proxyB isKindOfClass:[NSString class]]);
结果会输出完成不同的结论:
12
1 01 0
也就是说通过继承自NSObject的代理类是不会自动转发respondsToSelector:和isKindOfClass:这两个方法的, 而继承自NSProxy的代理类却是可以的. 测试<NSObject>
中定义的其它接口二者表现都是一致的.
2.NSObject的所有Category中定义的方法无法在THProxyB中完成转发
举一个很常见的例子, valueForKey:是定义在NSKeyValueCoding这个NSObject的Category中的方法, 尝试二者执行的表现.
12
NSLog(@"%@",[proxyA valueForKey:@"length"]);NSLog(@"%@",[proxyB valueForKey:@"length"]);
这段代码第一句能正确运行, 但第二行却会抛出异常, 分析最终原因其实很简单, 因为valueForKey:是NSObject的Category中定义的方法, 让NSObject具备了这样的接口, 而消息转发是只有当接收者无法处理时才会通过forwardInvocation:来寻求能够处理的对象.
3.结论: 如此看来NSProxy确实更适合实现做为消息转发的代理类, 因为作为一个抽象类, NSProxy自身能够处理的方法极小(仅<NSObject>
接口中定义的部分方法), 所以其它方法都能够按照设计的预期被转发到被代理的对象中.
- 使用NSProxy和NSObject设计代理类的差异
- 使用NSProxy和NSObject设计代理类的差异
- 使用NSProxy实现代理模式
- oc中少见的不继承于NSObject 的类NSProxy?
- oc中少见的不继承于NSObject 的类NSProxy?
- NSProxy的使用
- NSProxy的使用
- [iOS]使用NSProxy实现代理模式
- NSObject,NSProxy以及异常处理
- NSProxy实现代理方法
- NSObject的使用
- NSProxy实现代理模式[转载]
- iOS CFObject和NSObject的相互转换(使用bridge)
- NSObject class和NSObject protocol的关系(抽象基类与协议)
- NSObject class和NSObject protocol的关系(抽象基类与协议)
- 浅谈C++和Java的设计差异
- libev和libevent的设计差异
- [译]libev和libevent的设计差异
- android-----滑动冲突解决案例
- map按value排序, oh my god
- PHP学习笔记-PHP与JavaScript的交互
- Mybatis中的resultType和resultMap
- Mac OS安装maven
- 使用NSProxy和NSObject设计代理类的差异
- 2014.10.17 PLC S7-200 Hello world
- 让UIWebview拥有超强的图片处理能力
- 【CDP-云设计模式】第2章,1.快照模式(Snapshot Pattern)
- AddType requires at least two arguments, a mime type followed by one or more file extensions
- http协议
- 研发项目经理为何难做
- Spark在美团的实践
- 西门子 PLC S7-200的整数转换为ASCII码指令