Objective-C中的复制忍者卡卡西---NSProxy

是否是曾经在别人面前夸下海口:Objective-C中全部的类的基类都是NSObject;我以前也一直也这么觉得的,可是认真看了下官方文档:java

啪啪,好响,好疼~(看来英文水平也很重要啊......) 不卖关子了,咱们今天要讨论的就是NSProxy。它是跟NSObject属于同一级别的类,是个抽象类,只是实现了<NSObject>的协议;编程

按照官方的定义:NSProxy是一个为对象定义接口的抽象父类,而且为其它对象或者一些不存在的对象扮演了替身角色。一般,给proxy的消息被转发给实际对象或者致使proxy加载(转化它为)实际对象。NSProxy的子类能被用来实现透明的分布式消息(例如:NSDistantObject)或者延缓要花费昂贵代价建立的对象的实现。app

下面咱们看看NSProxy是怎么复制别的类(几乎全部类)的:分布式

咱们先建立一个类继承自NSProxy:学习

#import "KakashiProxy.h"

@interface KakashiProxy ()

@property(nonatomic,strong)NSObject *objc;

@end

@implementation KakashiProxy

- (void)changeObj:(NSObject *)obj {
    
    self.objc = obj;
    
}

//方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    
    NSMethodSignature *signature = nil;
    if ([self.objc methodSignatureForSelector:sel]) {
        signature = [self.objc methodSignatureForSelector:sel];
    }else {
        signature = [super methodSignatureForSelector:sel];
    }
    
    return signature;
}

//调用方法实现
- (void)forwardInvocation:(NSInvocation *)invocation {
    
    if ([self.objc respondsToSelector:invocation.selector]) {
        NSString *selName = NSStringFromSelector(invocation.selector);
        NSLog(@"selector name : %@",selName);
        //这里咱们能够作一些逻辑处理,好比埋点统计之类的
        [invocation invokeWithTarget:self.objc];
    }else {
        [super forwardInvocation:invocation];
    }
    
}

@end
复制代码

能够看到咱们重写了两个方法:methodSignatureForSelector:forwardInvocation:(NSInvocation *)invocation,前者是实现方法签名的,咱们能够在这个方法中,直接将咱们复制的对象进行方法签名,而后生成NSInvocation。接着方法forwardInvocation会被调用,在这个方法中,咱们直接将invacationtarget设置为咱们复制的对象。在这个方法中咱们能够作一点事情,好比根据类名作一些逻辑,也能够作一些数据埋点之类的。 而后咱们看看怎么使用这个复制忍者的: 咱们随便定义两个类,并为每一个类设置了一个方法:atom

Parker-Dog.hspa

#import "Parker-Dog.h"
    
    @implementation Parker_Dog
    
    - (void)bite {
        NSLog(@"卡卡西召唤通灵兽Paker并咬住了再不斩!");
    }
    
    @end
复制代码

Wood.h3d

#import "Wood.h"

    @implementation Wood
    
    - (void)boom{
    
        NSLog(@"变!木头!...");
        
    }
复制代码

调用:code

//初始化一个木头
    Wood *wood = [[Wood alloc] init];
    //初始化一个帕克
    Parker_Dog  *paker = [[Parker_Dog alloc] init];
    //初始化一个卡卡西
    KakashiProxy *proxy = [KakashiProxy alloc];
    
    //变木头
    [proxy changeObj:wood];
    //调用木头的方法
    [proxy performSelector:@selector(boom) withObject:nil];
    
    //变帕克
    [proxy changeObj:paker];
    //调用帕克的方法
    [proxy performSelector:@selector(bite) withObject:nil];
复制代码

控制台输出: orm

这样,咱们经过proxy这个类实现了复制woodpaker,能够分别调用各个类的方法了。

总结

其实也不能叫复制吧,你们也能够看到,这个实现其实就是利用了runtime的消息转发机制。这篇文章就算是对NSProxy的一个简单认识吧,还有些NSProxy的高级用法可能笔者尚未学习到,还要继续努力,有时间须要深刻研究下这个特殊的类。

参看文章

相关文章
相关标签/搜索