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

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

NSProxy是和NSObject同级的一个类,可以说它是一个虚拟类,它只是实现了<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. iOS NSProxy 的简单介绍和使用

    1.首先简单说一下OC消息发送机制 消息发送分两步: 第一步,编译阶段 不带参数:objc_msgSend(receiver,selector) 带参数:objc_msgSend(recevier,s ...

  2. iOS之深入解析少见却神奇的NSProxy类的多种使用

    一.NSProxy 简介 NSProxy 是一个实现了 NSObject 协议类似于 NSObject 的抽象基类,是根类,与 NSObject 类似: NS_ROOT_CLASS @interfac ...

  3. iOS进阶 :【NSProxy模拟多继承】作为一个委托代理对象,将消息转发给一个真实的对象或者自己加载的对象

    文章目录 前言 I 模拟多继承 1.1 初始化委托对象,用于拦截 UITableView 的选中 cell 事件 1.2 重写-methodSignatureForSelector:方法(获取真实对象 ...

  4. iOS底层系列之<45>--内存管理<1>NSProxy的使用

    1.定时器无法释放问题 当使用定时器的时候,下面的情况,定时器是无法释放的 #import "TimeVC.h" #import "Temp.h" #impor ...

  5. 「iOS 面试之道」勘误(二)

    本文是「iOS 面试之道」勘误系列的第二篇. Swift 初始化方法描述的漏洞 书中 105 页的描述是:Swift 初始化方法必须保证所有非 Optional 的成员变量都完成初始化. 这个表述是不 ...

  6. iOS开发-Runtime详解(简书)

    简介 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的.比如: [receiver message]; // ...

  7. swift 组件化_打造完备的iOS组件化方案:如何面向接口进行模块解耦?

    作者 | 黑超熊猫zuik,一个修行中的 iOS 开发,喜欢搞点别人没搞过的东西,钻研过逆向工程.VIPER 架构和组件化. 关于组件化的探讨已经有不少了,在之前的文章 iOS VIPER架构实践(三 ...

  8. iOS之深入解析消息转发objc_msgSend的应用场景

    一.消息转发 现有如下示例: id o = [NSObject new]; [o lastObject]; 执行上面代码,程序会崩溃并抛出以下异常: [NSObject lastObject]: un ...

  9. iOS开发-开发总结(七)

    一:手势与ScrollView兼容问题 倘若在 ViewController 中添加了一个 TableView,那么很可能在侧滑返回的时候,反而先触发了 TableView 的上下滚动,这一点是非常恼 ...

最新文章

  1. bat 将war文件转换成ear文件
  2. ResNeSt之语义分割,ADE20K全新SoTA 47.6%
  3. Pheatmap热图的绘制及如何调整图片
  4. Erlang里实现MapReduce
  5. 四渎《构建之法》——计划估计、敏捷流程、项目经理和用户场景
  6. 事物 php,什么是php事务
  7. (47)FPGA指数运算符(V代码实现)
  8. Kali linux 全部版本镜像下载
  9. mysql 服务卸载不干净
  10. 广告投放系统数据表设计
  11. 树形DP-Bribing FIPA
  12. 【华为思科】访问web服务器
  13. axTOCControl.HitTest方法
  14. Java极简角色权限后台管理框架springboot manager
  15. PHP单例模式的本质
  16. C# 串口SerialPort方法详解
  17. Photoshop cc 2017
  18. 新概念英语(第二册)复习(原文及全文翻译)——Lesson 41 - Lesson 50
  19. 软件测试流程鱼骨图思维导图模板分享
  20. 读《致在大学里感到迷茫的你》有感

热门文章

  1. Linux中进程正常退出return和exit()的区别
  2. Go 1.5交叉编译
  3. Windows Phone开发(15):资源
  4. java 数据类型之原码,补码,反码
  5. Webdriver for python 入门示例2(浏览器句柄操作)
  6. IT民工系列——通用7130芯片视频采集卡 SDK 兼容任意天敏 宏视 等板卡
  7. swift的可选项--optional/?
  8. 精品软件 推荐 瑞星个人防火墙V16 新UI、新功能、新体验
  9. C#(SuperWebSocket)与websocket通信
  10. 让你的linux操作系统更加安全