Objective-C Runtime

Describes the macOS Objective-C runtime library support functions and data structures.
 
Overview(概述)
 
以下是官方文档中对Runtime给出的定义
The Objective-C runtime is a runtime library that provides support for the dynamic properties of the Objective-C language, and as such is linked to by all Objective-C apps.
正式runtime这一个库给予了Objective-C language动态的属性, 所有的OC App都可以直接使用它
 
You typically don't need to use the Objective-C runtime library directly when programming in Objective-C. This API is useful primarily for developing bridge layers between Objective-C and other languages, or for low-level debugging.
一般programming时不会直接使用到runtime库, runtime这一功能或者属性一般用在跨域语言编程, 或者在较底层的debug中

Note

 
All char * in the runtime API should be considered to have UTF-8 encoding.
在runtime API中所有char类型都是以UTF-8编码的
 
以上是文档中对runtime做的一些简单介绍
 
经过之前看过的其他人对runtime的经验总结和自己的实践, 目前对Runtime的概念:
 
消息动态解析
消息重定向
消息转发
 
动态解析 在运行时(程序运行中)动态地:
给类中的已经定义但尚未实现的方法, 动态地绑定实现方法
给类增加或绑定既未定义也未实现方法, 说简单就是给类增加方法
 
文档中接下来是runtime方法的介绍, 我们在暂停在这里 先对上面几个概念做一个简单的说明
 
在之前必要我们先来看下[receiver message];这句话的实现过程, 也就是消息机制是如何在运作的
 
 struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
每一个NSObject对象都有成员变量列表, 方法列表, 缓存, 接口列表
方法列表中存储方法的指针(IMP)
缓存中存储的是曾经被调用的方法
 
[receiver message];会被转换成消息发送的模式:
id objc_msgSend(id self, SEL _cmd, …);
 
当对象接收到消息时会按照以下顺序依次检查, 在任何一个环节如果被响应则结束 否则报错
-> 对象接收到消息
-> 查看缓存中是否有匹配的方法, 如果有则响应 否则继续
-> 查看方法列表中是否有匹配的方法, 如果有则响应 否则继续
-> 查看父类中是否有匹配的方法, 如果有则响应 否则继续
->进入动态解析 + (BOOL)resolveInstanceMethod:(SEL)sel, 如果有指定动态解析方法则响应 否则继续
->进入消息重定向 - (id)forwardingTargetForSelector:(SEL)aSelector, 如果有指定消息接收对象则将消息转由接收对象响应 否则继续
->开始消息转发 - (void)forwardInvocation:(NSInvocation *)anInvocation, 如果有指定转发对象则转发给该对象响应, 否则抛出异常
 
再消息转发前我们有两次机会来修改或者设定对象方法的实现
 
下面再逐一说说
动态解析
假如我们有一个ClassA, 在它的头文件中我们定义了一个- (void)printName;方法, 但我们并没有在.m文件中让它实现
如果我们直接在Viewcontroller中使用[[ClassA new] printName];程序不会出错 但也不会做任何事情
 我们可以重写resolveInstanceMethod:或者resolveClassMethod:方法, 在这里我们给printName方法添加实现
 /**
要动态绑定的方法 @param self 要绑定方法的对象
@param _cmd 方法信息
*/
void dynamicMethodIMP(id self, SEL _cmd) { NSLog(@"SEL: %s method is added", sel_getName(_cmd));
NSLog(@"Name: Jackey");
} /**
动态绑定和解析方法 @param sel 方法信息
@return 是否已经处理该方法
*/
+ (BOOL)resolveInstanceMethod:(SEL)sel { NSLog(@"SEL: %s method does not exist", sel_getName(sel)); if (sel == @selector(printName)) { class_addMethod ([self class], sel, (IMP) dynamicMethodIMP, "v@:");
return YES;
} return [super resolveInstanceMethod:sel];
}

这样我们再运行[[ClassA new] printName];就会输出Name: Jackey

重定向:

如果经过动态解析后, 消息还没有被响应就会进入到重定向阶段

我们可以重写- (id)forwardingTargetForSelector:(SEL)aSelector将消息重定向给可以响应的对象

 /**
方法重定向 @param aSelector 方法信息
@return 返回重定向后要相应的对象
*/
- (id)forwardingTargetForSelector:(SEL)aSelector { NSLog(@"Current class can't response to SEL: %s", sel_getName(aSelector)); if (aSelector == @selector(printRightName)) { NSLog(@"Forward to target: %@", [ClassB class]);
return [ClassB new];
} return [super forwardingTargetForSelector:aSelector]; }

最后如果前面都没有处理就会进入到消息转发,  我们可以通过重写

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector;

- (void)forwardInvocation:(NSInvocation *)anInvocation;

来自定义

 /**
转发前, 获取方法签名 @param selector 方法信息
@return NSInvocation消息对象
*/
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { NSString *sel = NSStringFromSelector(selector);
if ([sel rangeOfString:@"set"].location == ){ return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
}
else{ return [NSMethodSignature signatureWithObjCTypes:"@@:"];
}
} /**
转发 @param anInvocation 消息对象
*/
- (void)forwardInvocation:(NSInvocation *)anInvocation { NSLog(@"No class can't response to SEL: %s", sel_getName([anInvocation selector])); ClassC *c = [ClassC new];
if ([c respondsToSelector:[anInvocation selector]]) { NSLog(@"method apply deliver to %@", [ClassC class]);
[anInvocation invokeWithTarget:c];
} else { [super forwardInvocation:anInvocation];
}
}

消息的转发弥补了OC不能多继承的问题

最后我们来看下Method Swizzling

我们可以直接修改方法的指针, 让一个方法名指向其他的方法实现

 Method ori_method = class_getInstanceMethod([ClassB class], @selector(printRightName));
Method my_method = class_getInstanceMethod([ClassC class], @selector(printFamilyName)); method_exchangeImplementations(ori_method, my_method); [[ClassB new] printRightName];

使用method_exchangeImplementation交换了两个对象方法的指针

printRightName执行的实际是printFamilyName

Objective-C runtime初识的更多相关文章

  1. Objective C Runtime 开发介绍

    简介 Objective c 语言尽可能的把决定从编译推迟到链接到运行时.只要可能,它就会动态的处理事情.这就意味着它不仅仅需要一个编译器,也需要一个运行时系统来执行变异好的代码.运行时系统就好像是O ...

  2. Runtime初识

    什么是Runtime   我们写的代码在程序运行过程中都会被转化成runtime的C代码执行,例如[target doSomething];会被转化成objc_msgSend(target, @sel ...

  3. 刨根问底Objective-C Runtime(4)- 成员变量与属性

    http://chun.tips/blog/2014/11/08/bao-gen-wen-di-objective[nil]c-runtime(4)[nil]-cheng-yuan-bian-lian ...

  4. Runtime-b

    感谢大神分享 依旧是网上很多runtime的资料,依旧是看不懂,,,这里给大家转化一下runtime,使它由隐晦难懂变得通俗易懂. (虽然截图和语言组织的有些凌乱,但是大家还是一点一点的阅读下去吧,可 ...

  5. Objective-C Runtime(一)预备知识

    很早就知道了Objective-C Runtime这个概念,「Objective-C奇技淫巧」「iOS黑魔法」各种看起来很屌的主题中总会有它的身影:但一直没有深入去学习,一来觉得目前在实际项目中还没有 ...

  6. iOS-运行时机制

    这里的两篇运行时的文章感觉还不错. 收藏: 初识iOS运行时RunTime | // TODO: http://www.saitjr.com/ios/objc-runtime.html Objecti ...

  7. 据说是百度ios面试题

    百度面试题:   一面:知识点 Objective C runtime library: Objective C的对象模型,Block的底层实现结构,消息发送,消息转发,内存管理 CoreData : ...

  8. iOS 面试基础题目

    转载: iOS 面试基础题目 题目来自博客:面试百度的记录,有些问题我能回答一下,不能回答的或有更好的回答我放个相关链接供参考. 1面 Objective C runtime library:Obje ...

  9. objc_msgSend消息传递学习笔记 – 消息转发

    该文是 objc_msgSend消息传递学习笔记 – 对象方法消息传递流程 的基础上继续探究源码,请先阅读上文. 消息转发机制(message forwarding) Objective-C 在调用对 ...

随机推荐

  1. Sublime Text3安装JsHint

    介绍 Sublime Text3使用jshint依赖Nodejs,SublimeLinter和Sublimelinter-jshint. NodeJs的安装省略. 安装SublimeLinter Su ...

  2. ASP.NET Core HTTP 管道中的那些事儿

    前言 马上2016年就要过去了,时间可是真快啊. 上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情.首先是 NPOI ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(74)-微信公众平台开发-自定义菜单

    系列目录 引言 1.如果不借用Senparc.Weixin SDK自定义菜单,编码起来,工作量是非常之大 2.但是借助SDK似乎一切都是简单得不要不要的 3.自定义菜单无需要建立数据库表 4.自定义菜 ...

  4. CSS 特殊属性介绍之 pointer-events

    首先看一下 MDN 上关于 pointer-events 的介绍: CSS属性 pointer-events 允许作者控制特定的图形元素在何时成为鼠标事件的 target.当未指定该属性时,SVG 内 ...

  5. 关于面试题 Array.indexof() 方法的实现及思考

    这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了. 昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法. 对于想进大公 ...

  6. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之目录导航

    ASP.NET MVC with Entity Framework and CSS是2016年出版的一本比较新的.关于ASP.NET MVC.EF以及CSS技术的图书,我将尝试着翻译本书以供日后查阅. ...

  7. iOS逆向工程之Hopper中的ARM指令

    虽然前段时间ARM被日本软银收购了,但是科技是无国界的,所以呢ARM相关知识该学的学.现在看ARM指令集还是倍感亲切的,毕竟大学里开了ARM这门课,并且做了不少的实验,当时自我感觉ARM这门课学的还是 ...

  8. PHP设计模式(六)原型模式(Prototype For PHP)

    原型设计模式: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型设计模式简单的来说,顾名思义, 不去创建新的对象进而保留原型的一种设计模式. 缺点:原型设计模式是的最主要的缺点就 ...

  9. Android 关于ijkplayer

    基于ijkplayer封装支持简单界面UI定制的视频播放器 可以解析ts格式的so库 怎样编译出可以解析ts等格式的so库?就是编译的时候需要在哪一步修改配置? 一些电视台的m3u8 CCTV1综合, ...

  10. iOS开源项目周报1222

    由OpenDigg 出品的iOS开源项目周报第二期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开发方面的开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等. io ...