Objective-c 语言中的类在声明时,必须指明它的父类。 NSObject
和 NSProxy
是 Objective-c提供的顶级父类,每一个OC类最终都会继承其中一个。绝大部分的OC类都会继承于NSObject
,而少部分继承于NSProxy
。
NSProxy
NSProxy
是一个抽象父类,定义了一套API,作为其他对象或者不存在的对象的替身或者代理。
通常,当NSProxy
收到消息,会转发给真实的对象或者加载真实对象(真实对象懒加载)。NSProxy
的子类必须实现分发消息和创建初始化真实对象的逻辑。
NSProxy子类的实现
NSProxy
实现了根父类必须的基本方法,包括NSObject
协议声明的方法。但是,作为抽象类它没有提供任何初始化方法,并且当收到无法处理的消息时会抛出异常。
NSProxy
派生的子类必须提供初始化方法并重写forwardInvocation:
和methodSignatureForSelector:
方法。
最佳实践 利用NSProxy实现弱引用代理
利用NSProxy
作为真实对象的代理,发送到NSProxy
的消息都会转发到真实对象。真实对象以弱引用的方式被NSProxy持有。
这种设计常常在需要避免引用循环的时候使用。
// 在这个方法中,target会被NSTimer强引用
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
提供初始化方法
// 为NSProxy提供初始化的方法,并声明一个弱引用属性保存真实对象
@interface ZLWeakProxy : NSProxy
@property(nonatomic, weak, readonly) id object;
- (instancetype) initWithObject:(id) object;
+ (instancetype) proxyWithObject:(id) object;
@end
@implementation ZLWeakProxy
- (instancetype) initWithObject:(id)object {
_object = object;
return self;
}
+ (instancetype) proxyWithObject:(id)object {
return [[self alloc] initWithObject:object];
}
@end
重写NSProxy的基本方法
// 调用基本方法重写为调用真实对象的相应方法
@implementation ZLWeakProxy
- (BOOL)isEqual:(id)object{
return [_object isEqual:object];
}
- (NSUInteger) hash {
return [_object hash];
}
- (Class) class {
return [_object class];
}
- (Class)superclass {
return [_object superclass];
}
- (BOOL)isKindOfClass:(Class)aClass{
return [_object isKindOfClass:aClass];
}
- (BOOL)isMemberOfClass:(Class)aClass{
return [_object isMemberOfClass:aClass];
}
- (BOOL)conformsToProtocol:(Protocol *)aProtocol{
return [_object conformsToProtocol:aProtocol];
}
- (BOOL) respondsToSelector:(SEL)aSelector {
return [_object respondsToSelector:aSelector];
}
- (BOOL) isProxy {
return YES;
}
- (NSString *)description {
return [_object description];
}
- (NSString *)debugDescription {
return [_object debugDescription];
}
@end
重写消息转发的方法
// 利用消息转发机制 将无法识别的消息转发给真实的对象
@implementation ZLWeakProxy
- (id)forwardingTargetForSelector:(SEL)selector {
return _object;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
void *null = NULL;
[invocation setReturnValue:&null];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
return [_object methodSignatureForSelector:sel];
}
@end
PREVIOUSObjective-c 消息发送与消息转发
NEXTObjective-c KVC