NSProxy学习

来源:互联网 发布:网络玄幻小说合集下载 编辑:程序博客网 时间:2024/06/04 19:38

NSProxy学习

 NSProxyObjective-C中的基类,这个类到底是做什么的呢,有什么用呢?Apple的官方文档是这样介绍的:

NSProxy is an abstract superclassdefining an API for objects that act as stand-ins for other objects or forobjects that don’t exist yet. Typically, a message to a proxy is forwarded tothe real object or causes the proxy to load (or transform itself into) the realobject. Subclasses of NSProxy can be used to implement transparent distributedmessaging (for example, NSDistantObject) or for lazy instantiation of objects that are expensiveto create.

总的来说,NSProxy是一个虚类,你可以通过继承它,并重写以下两个方法实现消息转发的

-(void)forwardInvocation:(NSInvocation *)invocation;-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel

我们可以大体了解NSProxy主要是做什么了,我们可以使用NSProxy的消息转发机制,来转发可由其它类的对象处理的任务,达成类似多重继承的目的。

通过NSProxyObjective-C中实现多继承目的

以下是一个例子和说明:

#import <Foundation/Foundation.h>@protocol YLHaveAMeetProtocpl <NSObject>-(void)haveAMeetWith:(NSString *)aperson;@end@interface YLHaveAMeet : NSObject@end
首先声明一个类YLHaveAMeet,它遵守协议YLHaveAMeetProtocpl,

#import "YLHaveAMeet.h"@interface YLHaveAMeet()<YLHaveAMeetProtocpl>@end@implementation YLHaveAMeet-(void)haveAMeetWith:(NSString *)aperson{    NSLog(@"开会了:%@",aperson);}@end

这里要注意:一定要通过protocol来声明接口,而不是直接在类的@interfere中定义。因为通过protocol来声明接口,然后让proxy类遵循此协议,可以骗过编译器防止编译器提示proxy类未声明接口的错误。这个问题下面可以看到。

 然后是另一个类YLPrepareDinner,遵守协议YLPrepareDinnerProtocol,

#import <Foundation/Foundation.h>@protocol YLPrepareDinnerProtocol <NSObject>-(void)haveADinner;@end@interface YLPrepareDinner : NSObject@end
实现代码:

#import "YLPrepareDinner.h"@interface YLPrepareDinner ()<YLPrepareDinnerProtocol>@end@implementation YLPrepareDinner-(void)haveADinner{    NSLog(@"you should eat up");}@end

写完这两个类,我们就要用到NSProxy了。

 

#import <Foundation/Foundation.h>#import "YLHaveAMeet.h"#import "YLPrepareDinner.h"@interface YLShouldDoProxy : NSProxy<YLPrepareDinnerProtocol,YLHaveAMeetProtocpl>+(instancetype)proxy;@end
#import "YLShouldDoProxy.h"#import <objc/runtime.h>@implementation YLShouldDoProxy{    YLHaveAMeet *_meet;    YLPrepareDinner *_dinner;    NSMutableDictionary *_methodsMap;}+(instancetype)proxy{    return [[YLShouldDoProxy alloc]init];}-(instancetype)init{    _methodsMap=[[NSMutableDictionary alloc]init];    _meet=[[YLHaveAMeet alloc]init];    _dinner=[[YLPrepareDinner alloc]init];    [self registerMethodsWithTarget:_meet];    [self registerMethodsWithTarget:_dinner];    return self;}-(void)registerMethodsWithTarget:(id)target{    unsigned int methodNum=0;    Method *methodList=class_copyMethodList([target class], &methodNum);        for (int i=0; i<methodNum; i++) {        Method currentMethod=methodList[i];        SEL currentSEL=method_getName(currentMethod);        const char *current_method_name=sel_getName(currentSEL);        [_methodsMap setObject:target forKey:[NSString stringWithUTF8String:current_method_name]];    }    free(methodList);}-(void)forwardInvocation:(NSInvocation *)invocation{    SEL sel=invocation.selector;    NSString *methodName=NSStringFromSelector(sel);    id target=_methodsMap[methodName];        if ([target respondsToSelector:sel]&&target) {        [invocation invokeWithTarget:target];    }else{        [super forwardInvocation:invocation];    }}-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel{    NSString *methodName=NSStringFromSelector(sel);    id target=_methodsMap[methodName];        if (target&&[target respondsToSelector:sel]) {        return [target methodSignatureForSelector:sel];    }else{        return [super methodSignatureForSelector:sel];    }}

好了,我们需要做的就是把我们要做的交给NSProxy就可以了。

YLShouldDoProxy *sholdDo=[YLShouldDoProxy proxy];[sholdDo haveAMeetWith:@"你是谁?"];[sholdDo haveADinner];return YES;
运行结果如下:

2017-04-17 21:06:20.034 YLProxy[18471:639293] 开会了:你是谁?

2017-04-17 21:06:20.034 YLProxy[18471:639293] you should eat up

大功告成!
 
0 0
原创粉丝点击