NSProxy
An abstract superclass defining an API for objects that act as stand-ins for other objects or for objects that don’t exist yet.
也就是说它是一个抽象超类,为子类对象定义API
@interface NSProxy <NSObject> {
Class isa;
}
通常,当有消息发送给NSProxy,需要转发给实际对象,NSproxy遵循NSObject协议,提供了消息转发的通用接口,它只是实现了一些基础方法,但是它并不提供初始化方法,当收到一些它无法响应的消息时,它会直接抛出异常。
使用NSProxy,需要创建一个子类,需要做这些事:
-
提供初始化方法
-
重写methodSignatureForSelector:
methodSignatureForSelector需要给消息参数提供类型,并构造NSMethodSignature 对象 -
respondsToSelector:
是否响应一个SEL -
重写forwardInvocation:
forwardInvocation应该处理整个调用流程所需要的任何操作,例如通过网络转发调用或加载实际对象并将调用传递给它
实际应用
使用NSProxy来避免循环引用
使用WeakProxy来实现弱引用
创建NSProxy子类
WeakProxy.h
@interface WeakProxy : NSProxy
@property (weak,nonatomic,readonly)id target;
+ (instancetype)proxyWithTarget:(id)target;
- (instancetype)initWithTarget:(id)target;
@end
WeakProxy.m
#import "WeakProxy.h"
@implementation WeakProxy
- (instancetype)initWithTarget:(id)target{
_target = target;
return self;
}
+ (instancetype)proxyWithTarget:(id)target{
return [[self alloc] initWithTarget:target];
}
- (void)forwardInvocation:(NSInvocation *)invocation{
SEL sel = [invocation selector];
if ([self.target respondsToSelector:sel]) {
[invocation invokeWithTarget:self.target];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSMethodSignature *s = [self.target methodSignatureForSelector:aSelector];
return s;
}
- (BOOL)respondsToSelector:(SEL)aSelector{
return [self.target respondsToSelector:aSelector];
}
@end
self.timer = [NSTimer timerWithTimeInterval:1
target:[WeakProxy proxyWithTarget:self]
selector:@selector(print:)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
实现多继承
创建NSProxy子类TargetProxy
TargetProxy.h
@interface TargetProxy : NSProxy
- (id)initWithTarget1:(id)t1 target2:(id)t2;
@end
创建Study类
@interface Student : NSObject
- (void)study;
@end
TargetProxy.m
@interface TargetProxy ()
@property(nonatomic, strong) id realObject1;
@property(nonatomic, strong) id realObject2;
@end
@implementation TargetProxy
- (id)initWithTarget1:(id)t1 target2:(id)t2 {
self.realObject1 = t1;
self.realObject2 = t2;
return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature *sig;
sig = [self.realObject1 methodSignatureForSelector:aSelector];
if (sig) return sig;
sig = [self.realObject2 methodSignatureForSelector:aSelector];
return sig;
}
// Invoke the invocation on whichever real object had a signature for it.
- (void)forwardInvocation:(NSInvocation *)invocation {
id target = [self.realObject1 methodSignatureForSelector:[invocation selector]] ? self.realObject1 : self.realObject2;
[invocation invokeWithTarget:target];
}
// Override some of NSProxy's implementations to forward them...
- (BOOL)respondsToSelector:(SEL)aSelector {
if ([self.realObject1 respondsToSelector:aSelector]) return YES;
if ([self.realObject2 respondsToSelector:aSelector]) return YES;
return NO;
}
NSMutableString *string = [[NSMutableString alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] init];
id proxy = [[TargetProxy alloc] initWithTarget1:string target2:array];
[proxy appendString:@"This "];
[proxy appendString:@"is "];
[proxy addObject:string];
[proxy appendString:@"a "];
[proxy appendString:@"test!"];
NSLog(@"count should be 1, it is: %lu", (unsigned long)[proxy count]);
if ([[proxy objectAtIndex:0] isEqualToString:@"This is a test!"]) {
NSLog(@"Appending successful.");
} else {
NSLog(@"Appending failed, got: '%@'", proxy);
}
这样TargetProxy就同时继承了NSMutableString类和NSMutableArray类
网友评论