美文网首页
NSProxy的理解

NSProxy的理解

作者: skogt | 来源:发表于2019-05-13 18:09 被阅读0次

什么是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.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 implements the basic methods required of a root class, including those defined in the NSObject protocol. However, as an abstract class it doesn’t provide an initialization method, and it raises an exception upon receiving any message it doesn’t respond to. A concrete subclass must therefore provide an initialization or creation method and override the forwardInvocation: and methodSignatureForSelector: methods to handle messages that it doesn’t implement itself. A subclass’s implementation of forwardInvocation: should do whatever is needed to process the invocation, such as forwarding the invocation over the network or loading the real object and passing it the invocation. methodSignatureForSelector: is required to provide argument type information for a given message; a subclass’s implementation should be able to determine the argument types for the messages it needs to forward and should construct an NSMethodSignature object accordingly. See the NSDistantObject, NSInvocation, and NSMethodSignature class specifications for more information.

这是苹果官方对于NSProxy的解释。这边简单的翻译下:

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正是代理的意思。

其中,我觉得NSProxy最重要且最核心的一点是消息分发。根据这个特性,我们可以提升项目代码的可维护性,更加模块化。

下面是对NSProxy使用的demo,对消息做分发

/// 农民工协议
@protocol WorkerProtocol <NSObject>

- (void)beginWork;

@end

NS_ASSUME_NONNULL_BEGIN

@interface Worker : NSObject <WorkerProtocol>

@end

NS_ASSUME_NONNULL_END
/// 码农协议
@protocol ITerProtocol <NSObject>

- (void)beginCoding;

@end

NS_ASSUME_NONNULL_BEGIN

@interface ITer : NSObject <ITerProtocol>

@end

NS_ASSUME_NONNULL_END
/// 消息分发中心
@interface MsgDistProxy : NSProxy <WorkerProtocol, ITerProtocol>
+ (instancetype)sharedInstance;
- (void)registerMethodWithTarget:(id)target;
@end
@interface MsgDistProxy()
@property (nonatomic, strong) NSMutableDictionary *selectorMapDic;
@end

@implementation MsgDistProxy

+ (instancetype)sharedInstance {
    static MsgDistProxy *proxy;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        proxy = [MsgDistProxy 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);
        [self.selectorMapDic setValue:target forKey:[NSString stringWithUTF8String:sel_getName(selector)]];
    }
    free(methodlist);
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    NSString *selector = NSStringFromSelector(sel);
    if ([self.selectorMapDic.allKeys containsObject:selector]) {
        id target = [self.selectorMapDic objectForKey:selector];
        return [target methodSignatureForSelector:sel];
    }
    return [super methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    NSString *selector = NSStringFromSelector(invocation.selector);
    if ([self.selectorMapDic.allKeys containsObject:selector]) {
        id target = [self.selectorMapDic objectForKey:selector];
        [invocation invokeWithTarget:target];
    } else {
        [super forwardInvocation:invocation];
    }
}

@end
    /// 调用
    MsgDistProxy *proxy = [MsgDistProxy sharedInstance];
    
    Worker *worker = [Worker new];
    ITer *iter = [ITer new];
    
    [proxy registerMethodWithTarget:worker];
    [proxy registerMethodWithTarget:iter];
    
    [proxy beginWork];
    [proxy beginCoding];

    /// 输出log
  2019-05-13 17:41:12.148984+0800 proxy[19121:933997] -[Worker beginWork]
  2019-05-13 17:41:12.149197+0800 proxy[19121:933997] -[ITer beginCoding]

相关文章

  • NSProxy的理解

    什么是NSProxy An abstract superclass defining an API for obj...

  • 2019-08-22 swift 实现YYWeakProxy

    参考文献:NSProxy 一些 使用关于NSProxy的理解Swift中Timer的循环引用解决方案(类似NSPr...

  • 重拾iOS-NSProxy

    关键词:NSProxy,NSObject,Runtime 面试题:1)知道NSProxy吗?2)NSProxy和N...

  • 解密NSproxy的面纱

    NSProxyDemo该文章介绍NSProxy这个类。 先给代码地址: NSProxyDemo 在我理解,主要是一...

  • NSProxy

    NSProxy.h文件内容 NSProxy 是一个抽象类NSProxy遵守了 NSObject 协议,内部有它的 ...

  • NSProxy、NSInvocation、NSMethodSig

    什么是NSProxy: NSProxy是一个抽象的基类,是根类,与NSObject类似 NSProxy和NSObj...

  • 关于 NSProxy 的理解与运用

    什么是 NSProxy 首先,我们看下官方给出的定义 NSProxy 是一个为对象定义接口的抽象父类,它为充当其他...

  • [iOS] 七七八八的小姿势(2)

    目录: NSProxy 字典集合对成员的引用方式 class判断 block变量捕获 1. NSProxy NSP...

  • NSProxy 和 NSObject 关系

    一、NSProxy 简介NSProxy 是一个抽象类,它实现了protocol NSObject 所要求的基本方法...

  • 老生常谈之NSProxy和NSTimer

    网上NSProxy和NSTimer都写烂了,所以这里只做下总结: 1.NSProxy应用场景: 解决NSTimer...

网友评论

      本文标题:NSProxy的理解

      本文链接:https://www.haomeiwen.com/subject/sfuraqtx.html