NSProxy的理解和使用

1.NSProxy的定义

NSProxy is an abstract superclass defining an API for objects that act as stand-ins for other objects or for objects that don’t exist yet. Typically, a message to a proxy is forwarded to the real object or causes the proxy to load (or transform itself into) the real object. Subclasses of NSProxy can be used to implement transparent distributed messaging (for example, NSDistantObject) or for lazy instantiation of objects that are expensive to create.
复制代码

翻译:NSProxy是一个抽象的超类,它定义了一个对象的API,用来充当其他对象或者一些不存在的对象的替身。通常,发送给Proxy的消息会被转发给实际对象,或使Proxy加载(转化为)实际对象。 NSProxy的子类可以用于实现透明的分布式消息传递(例如,NSDistantObject),或者用于创建开销较大的对象的惰性实例化。

 众所周知,NSObject类是Objective-C中大部分类的基类。但不是很多人知道除了NSObject之外的另一个基类——NSProxy,NSProxy实现被根类要求的基础方法,包括定义NSObject协议。然而,作为抽象类,它不实现初始化方法,并且会在收到任何它不响应的消息时引发异常。因此,具体子类必须实现一个初始化或者创建方法,并且重写- (void)forwardInvocation:(NSInvocation *)invocation;和- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel方法,来转发它没实现的方法。这也是NSProxy的主要功能,负责把消息转发给真正的target的代理类,NSProxy正是代理的意思。

2.NSProxy的使用

  1. 模拟多继承

    多继承可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承。大家知道,Objective-C不支持多继承,但是NSProcy可以在一定程度上解决这个问题,但需要注意的是,这只是一个模拟的多继承,并不是完全的多继承。接下来,我们看一个官方的例子:

    @interface TargetProxy : NSProxy
     {
         id realObject1;
         id realObject2;
     }
     -(id)initWithTarget1:(id)t1 target:(id)t2;
     
     @end
     
     @implementation TargetProxy
     
     -(id)initWithTarget1:(id)t1 target:(id)t2
     {
           realObject1 = t1;
           realObject2 = t2;
           return self;
     }
     -(void)forwardInvocation:(NSInvocation *)invocation
     {
            id target = [realObject1 methodSignatureForSelector:invocation.selector]?realObject1:realObject2;
            [invocation invokeWithTarget:target];
     }
     -(NSMethodSignature *)methodSignatureForSelector:(SEL)sel
     {
          NSMethodSignature *signature;
          signature = [realObject1 methodSignatureForSelector:sel];
          if (signature) {
               return signature;
          }
          signature = [realObject2 methodSignatureForSelector:sel];
          return signature;
     }
     -(BOOL)respondsToSelector:(SEL)aSelector
     {
          if ([realObject1 respondsToSelector:aSelector]) {
             return YES;
          }
          if ([realObject2 respondsToSelector:aSelector]) {
             return YES;
           }
         return NO;
     }
     @end
     
     使用案例:
     NSMutableArray *array = [NSMutableArray array];
     NSMutableString *string = [NSMutableString string];
     
     id proxy = [[TargetProxy alloc]initWithTarget1:array target:string];
     [proxy appendString:@"This "];
     
     [proxy appendString:@"is "];
     [proxy addObject:string];
     [proxy appendString:@"a "];
     [proxy appendString:@"test!"];
      NSLog(@"count should be 1,it is:%ld",[proxy count]);
     if ([[proxy objectAtIndex:0] isEqualToString:@"This is a test!"]) {
         NSLog(@"Appending successful: %@",proxy);
     }else
     {
         NSLog(@"Appending failed, got: %@", proxy);
     }
         NSLog(@"Example finished without errors.");
     //TargetProxy拥有了NSSting与NSArray俩个类的方法属性
    
    复制代码
  2. 解决NSTimer无法释放的问题

    解决NSTimer的内存泄漏问题

  3. 实现两个甚至多个不同对象的消息分发

#import <Foundation/Foundation.h>
 
 @protocol TeacherProtocol <NSObject>
 - (void)beginTeachering;
 @end
 
 @interface Teacher : NSObject
 
 @end

 #import "Teacher.h"
 
 @implementation Teacher
 
 -(void)beginTeachering
 {
     NSLog(@"%s",__func__);
 }
 @end

 #import <Foundation/Foundation.h>
 
 @protocol StudentProtocol <NSObject>
  - (void)beginLearning;
 @end
 
 
 @interface Student : NSObject
 @end
 
 #import "Student.h"
 
 @implementation Student
 
 -(void)beginLearning
 {
     NSLog(@"%s",__func__);
 }
 @end

 #import <Foundation/Foundation.h>
 #import "Teacher.h"
 #import "Student.h"
 
 @interface JSDistProxy : NSProxy<TeacherProtocol,StudentProtocol>
 +(instancetype)sharedInstance;
 -(void)registerMethodWithTarget:(id)target;
 @end

 #import "JSDistProxy.h"
 #import <objc/runtime.h>
 
 @interface JSDistProxy ()
 @property(nonatomic,strong) NSMutableDictionary *selectorMapDic;
 @end
 
 
 @implementation JSDistProxy
 
 +(instancetype)sharedInstance
 {
    static JSDistProxy *proxy;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
       proxy = [JSDistProxy alloc];
       proxy.selectorMapDic = [NSMutableDictionary dictionary];
    });
     return proxy;
 }
 -(void)registerMethodWithTarget:(id)target
 {
     unsigned int count = 0;
     Method *methodList = class_copyMethodList([target class], &count);
     for (int i=0; i<count; i++) {
          Method method = methodList[i];
          SEL selector = method_getName(method);
          const char *method_name = sel_getName(selector);
         [self.selectorMapDic setValue:target forKey:[NSString stringWithUTF8String:method_name]];
     }
     free(methodList);
 }
 
 -(NSMethodSignature *)methodSignatureForSelector:(SEL)sel
 {
       NSString *methodStr = NSStringFromSelector(sel);
       if ([self.selectorMapDic.allKeys containsObject:methodStr]) {
       id target = self.selectorMapDic[methodStr];
           return [target methodSignatureForSelector:sel];
        }
       return [super methodSignatureForSelector:sel];
 }
 -(void)forwardInvocation:(NSInvocation *)invocation
 {
        NSString *methodName = NSStringFromSelector(invocation.selector);
        if ([self.selectorMapDic.allKeys containsObject:methodName]) {
            id target = self.selectorMapDic[methodName];
            [invocation invokeWithTarget:target];
        }else
        {
            [super forwardInvocation:invocation];
         }
 }

 @end
 使用案例:
 JSDistProxy *proxy = [JSDistProxy sharedInstance];
 Teacher *teacher = [Teacher new];
 Student *student = [Student new];
 [proxy registerMethodWithTarget:teacher];
 [proxy registerMethodWithTarget:student];
 
 [proxy beginLearning];
 [proxy beginTeachering];
 //实现方法的实现与声明分离,提升项目代码的可维护性,更加模块化。
复制代码

参考资料:

关于NSProxy的理解

NSProxy——少见却神奇的类


转载于:https://juejin.im/post/5afbca7bf265da0b8c25251d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值