Objective-C作为一种动态消息型语言,其机制不同于Java ,C#等编译型语言.

它将数据类型的确定等工作推迟到了运行时期来执行,并且它调用方法的方式实质是像对象发送消息,根据selector在对象的本类以及父类中的方法列表进行查找,如果都找不到就会启动消息转发机制.

回到正题,这个话题我想谈下OC的单继承原则.

OC确实是只能单继承的语言,但是基于运行时的机制,却有一种方法让它来实现一下"伪多继承".就是利用NSProxy这个类.

NSProxy是和NSObject同级的一个类,可以说它是一个虚拟类,它只是实现了的协议.它的作用有点类似于一个复制类,有人曾经笑谈它是卡卡西的复制忍术,想想其实也挺贴切的,其实原理确实如此.

过程:

用一个继承于NSProxy的子类,在它内部实现一些方法,暴露一个公开方法transform,这个方法是使它变身的关键.然后它变身之后可以对那些对象发送消息,并且可以在内部拦截消息的内容并修改.

可以说,几乎可以变身成为任何对象.

直接上个代码来展示下

JanProxy.h

#import <Foundation/Foundation.h>

@interface JanProxy : NSProxy

- (void)transformObjc:(NSObject *)objc;

@end

JanProxy.m

#import "JanProxy.h"

@interface JanProxy ()

@property(nonatomic,strong)NSObject *objc;

@end

@implementation JanProxy

- (void)transformObjc:(NSObject *)objc
{
//复制对象
self.objc = objc;
} //2.有了方法签名之后就会调用方法实现
- (void)forwardInvocation:(NSInvocation *)invocation
{
if (self.objc) {
//拦截方法的执行者为复制的对象
[invocation setTarget:self.objc]; if ([self.objc isKindOfClass:[NSClassFromString(@"Cat") class]]) {
//拦截参数 Argument:表示的是方法的参数 index:表示的是方法参数的下标
NSString *str = @"拦截消息";
[invocation setArgument:&str atIndex:2];
} //开始调用方法
[invocation invoke];
} } //1.查询该方法的方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
NSMethodSignature *signature = nil;
if ([self.objc methodSignatureForSelector:sel]) {
signature = [self.objc methodSignatureForSelector:sel];
}
else
{
signature = [super methodSignatureForSelector:sel];
} return signature;
} @end

使用方法


Dog *dog = [[Dog alloc]init]; //OC中方法的调用本质上是给这个对象发送一个消息
Cat *cat = [[Cat alloc] init]; //开始复制拦截方法
JanProxy *proxy = [JanProxy alloc];
//开始变身成猫
[proxy transformObjc:cat];
//开始调猫的方法
[proxy performSelector:@selector(eat:) withObject:@"猫发出消息"]; //开始变身成狗
[proxy transformObjc:Dog];
//开始调用学生的方法
[proxy performSelector:@selector(shut)];

最后的结果

发现没有,猫发出消息已经被子类的内部拦截并且做出了修改.

总结

OC中存在这么一个默默无闻的类NSProxy,填补了"多继承"这个空白区.

iOS | NSProxy的更多相关文章

  1. [转]NSProxy实现AOP方便为ios应用实现异常处理策略

    [转载自:http://blog.csdn.net/yanghua_kobe/article/details/8395535] 前段时间关注过objc实现的AOP,在GitHub找到了其中的两个库:A ...

  2. iOS 消息转发以及 NSProxy 实战

    最后更新: 2018-01-17 一.消息派发机制-NSObject 在 iOS 开发中, 调用对象的方法就是给对象发送一个消息.了解消息的派发机制对于iOS开发来说是一个很实用且强大的工具, 下面我 ...

  3. NSProxy实现AOP方便为ios应用实现异常处理策略

    前段时间关注过objc实现的AOP. 在GitHub找到了其中的两个库:AOP-in-Objective-C 和 AOP-for-Objective-C 第一个是基于NSProxy来实现的:第二个是基 ...

  4. iOS Class 使用NSProxy和NSObject设计代理类的差异

    经常发现在一些需要使用消息转发而创建代理类时, 不同的程序员都有着不同的使用方法, 有些采用继承于NSObject, 而有一些采用继承自NSProxy. 二者都是Foundation框架中的基类, 并 ...

  5. iOS开发——高级特性&Runtime运行时特性详解

    Runtime运行时特性详解 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的动态特性,使这门古老的语言焕发生机.主要内容如下: 引言 ...

  6. iOS RunTime运行时(1):类与对象

    Objective-C语言是一门动态语言,他将很多静态语言在编译和链接期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码更具有灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一下 ...

  7. iOS运行时Runtime浅析

    运行时是iOS中一个很重要的概念,iOS运行过程中都会被转化为runtime的C代码执行.例如[target doSomething];会被转化成objc)msgSend(target,@select ...

  8. iOS经典面试题(转)

    iOS经典面试题   前言 写这篇文章的目的是因为前两天同学想应聘iOS开发,从网上找了iOS面试题和答案让我帮忙看看.我扫了一眼,倒吸了一口冷气,仔细一看,气的发抖.整篇题目30多个没有一个答案是对 ...

  9. iOS 简单工厂模式

    iOS 简单工厂模式 什么是简单工厂模式? 简单工厂模式中定义一个抽象类,抽象类中声明公共的特征及属性,抽象子类继承自抽象类,去实现具体的操作.工厂类根据外界需求,在工厂类中创建对应的抽象子类实例并传 ...

随机推荐

  1. 移动端适配(2)——viewport适配

    通过viewport来适配 <script> (function(){ var w=window.screen.width; console.log(w);//获取屏幕尺寸 var tar ...

  2. alert 多语言的处理

    1. code <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <m ...

  3. Spring Boot Async异步执行

    异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑. 通常我们使用异步操作都会去创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代码如下: Execut ...

  4. Android Animation 知识点速记备忘思维导图

    备注的大段文本,无法在图片中体现, 思维导图源文件放在附件中.使用 Xmind 8 制作. 附件:AndroidAnimation-xmind.zip

  5. Spring boot配置注意事项

    SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描! “Application类”是指SpringBoot项目入口类.这个类的位置很关键: 如果App ...

  6. mac apache服务器

    //开启apache: sudo apachectl start //重启apache: sudo apachectl restart //关闭apache: sudo apachectl stop ...

  7. Elasticsearch.yml

    cluster.name: elasticsearch配置es的集群名称,默认是elasticsearch,es会自动发现在同一网段下的es,如果在同一网段下有多个集群,就可以用这个属性来区分不同的集 ...

  8. GoAccess分析Nginx日志详解

    一.为了提高 GoAccess 分析准确度,建议配置 nginx.conf 的 log_format 项如下: log_format main '$remote_addr - $remote_user ...

  9. hdu 6208 The Dominator of Strings【AC自动机】

    hdu 6208 The Dominator of Strings[AC自动机] 求一个串包含其他所有串,找出最长串去匹配即可,但是匹配时要对走过的结点标记,不然T死QAQ,,扎心了.. #inclu ...

  10. BZOJ3238:[AHOI2013]差异(SAM)

    Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N< ...