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. 洛谷P3953 逛公园(dp 拓扑排序)

    题意 题目链接 Sol 去年考NOIP的时候我好像连最短路计数都不会啊qwq.. 首先不难想到一个思路,\(f[i][j]\)表示到第\(i\)个节点,与最短路之差长度为\(j\)的路径的方案数 首先 ...

  2. HTML总结摘要

    一 概述 1.什么是HTML? HyperText Markup Language,超文本标记语言,客户端技术的技术,负责页面展示. 2.HTML的特点 标签不区分大小写. 3.请求地址 HTML是客 ...

  3. pv-remjs的快速开始

    pv-remjs 这是一个移动端适配的工具类,采用rem布局的方式 ## 快速开始 在html文件中引入,先查看版本`<script src= "https://unpkg.com/p ...

  4. siriWave.js的demo

    demo.html <style>body { background: #000; }</style> <script src="../siriwave.js& ...

  5. Angular1组件通讯方式总结

    这里需要将Angular1分为Angular1.5之前和Angular1.5两个不同的阶段来讲,两者虽然同属Angular1,但是在开发模式上还是有较大区别的.在Angular1.4及以前,主要是基于 ...

  6. 二、Flex 布局教程:实例篇

    注:本文转自大神阮一峰,自己加了少许改动~ 上一篇文章介绍了Flex布局的语法,今天介绍常见布局的Flex写法. 你会看到,不管是什么布局,Flex往往都可以几行命令搞定. 我只列出代码,详细的语法解 ...

  7. UVaOJ 694 - The Collatz Sequence

    题目很简单,但是一开始却得到了Time Limit的结果,让人感到很诧异.仔细阅读发现,题目中有一个说明: Neither of these, A or L, is larger than 2,147 ...

  8. Oracle案例06—— OGG-01098 Could not flush "./dirdat/e1000004383" (error 28, No space left on device)

    一.前言 自从换了新环境,各种问题层出不穷,如果不是之前积累的经验丰富,估计都歇菜了,看来作为数据库全栈工程师(oracle/mysql/sqlserver/sap hana/pg/mongodb/r ...

  9. 旋转动画用控件RotateView

    旋转动画用控件RotateView 最终效果: 源码: RotateView.h 与 RotateView.m // // RotateView.h // RotateAnimationView // ...

  10. CVE-2016-3231

    摘要:重现了下韩国小哥Lokihardt在pwn2own上的过沙箱提权漏洞. 1 #include <windows.h> 2 #include <atlbase.h> 3 # ...