博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Objective-C中的复制忍者卡卡西---NSProxy
阅读量:6303 次
发布时间:2019-06-22

本文共 2445 字,大约阅读时间需要 8 分钟。

是不是曾经在别人面前夸下海口:Objective-C中所有的类的基类都是NSObject;我之前也一直也这么以为的,但是认真看了下官方文档:

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

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

下面我们看看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设置为我们复制的对象。在这个方法中我们可以做一点事情,比如根据类名做一些逻辑,也可以做一些数据埋点之类的。 然后我们看看怎么使用这个复制忍者的: 我们随便定义两个类,并为每个类设置了一个方法:

Parker-Dog.h

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

Wood.h

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

调用:

//初始化一个木头    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];复制代码

控制台输出:

这样,我们通过proxy这个类实现了复制woodpaker,可以分别调用各个类的方法了。

总结

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

参看文章

转载地址:http://wmfxa.baihongyu.com/

你可能感兴趣的文章
OCP最新题库052考题解析及答案-第37题
查看>>
Linux服务器Java输出文件中文乱码
查看>>
利用剩余磁盘空间新建分区
查看>>
在程序中使用Response.End时发生异常“正在终止线程”
查看>>
FROM USE CASES TO TEST CASES
查看>>
linux 常用命令
查看>>
Java--运算符
查看>>
php总结3——基本函数、流程控制中的循环
查看>>
我的博客css得到别人的认可
查看>>
Dockerfile构建MySQL
查看>>
唯一正确的修改Jupyter Notebook默认路径的方法
查看>>
Python 基础学习之序列及列表操作小结
查看>>
实验五 网络对抗技术
查看>>
JSP+Servlet+DAO+Javabean模式小记-20171029
查看>>
android drawable size
查看>>
Linux 字符设备控制技术
查看>>
JavaScript循环读书笔记
查看>>
C++模式学习------单例模式
查看>>
PHP基础
查看>>
NUC1429 WERTYU【输入输出】
查看>>