Objective-C runtime初识
Objective-C Runtime
Note
char * in the runtime API should be considered to have UTF-8 encoding. 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;
id objc_msgSend(id self, SEL _cmd, …);
/**
要动态绑定的方法 @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初识的更多相关文章
- Objective C Runtime 开发介绍
简介 Objective c 语言尽可能的把决定从编译推迟到链接到运行时.只要可能,它就会动态的处理事情.这就意味着它不仅仅需要一个编译器,也需要一个运行时系统来执行变异好的代码.运行时系统就好像是O ...
- Runtime初识
什么是Runtime 我们写的代码在程序运行过程中都会被转化成runtime的C代码执行,例如[target doSomething];会被转化成objc_msgSend(target, @sel ...
- 刨根问底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 ...
- Runtime-b
感谢大神分享 依旧是网上很多runtime的资料,依旧是看不懂,,,这里给大家转化一下runtime,使它由隐晦难懂变得通俗易懂. (虽然截图和语言组织的有些凌乱,但是大家还是一点一点的阅读下去吧,可 ...
- Objective-C Runtime(一)预备知识
很早就知道了Objective-C Runtime这个概念,「Objective-C奇技淫巧」「iOS黑魔法」各种看起来很屌的主题中总会有它的身影:但一直没有深入去学习,一来觉得目前在实际项目中还没有 ...
- iOS-运行时机制
这里的两篇运行时的文章感觉还不错. 收藏: 初识iOS运行时RunTime | // TODO: http://www.saitjr.com/ios/objc-runtime.html Objecti ...
- 据说是百度ios面试题
百度面试题: 一面:知识点 Objective C runtime library: Objective C的对象模型,Block的底层实现结构,消息发送,消息转发,内存管理 CoreData : ...
- iOS 面试基础题目
转载: iOS 面试基础题目 题目来自博客:面试百度的记录,有些问题我能回答一下,不能回答的或有更好的回答我放个相关链接供参考. 1面 Objective C runtime library:Obje ...
- objc_msgSend消息传递学习笔记 – 消息转发
该文是 objc_msgSend消息传递学习笔记 – 对象方法消息传递流程 的基础上继续探究源码,请先阅读上文. 消息转发机制(message forwarding) Objective-C 在调用对 ...
随机推荐
- 设计爬虫Hawk背后的故事
本文写于圣诞节北京下午慵懒的午后.本文偏技术向,不过应该大部分人能看懂. 五年之痒 2016年,能记入个人年终总结的事情没几件,其中一个便是开源了Hawk.我花不少时间优化和推广它,得到的评价还算比较 ...
- 恢复SQL Server被误删除的数据
恢复SQL Server被误删除的数据 <恢复SQL Server被误删除的数据(再扩展)> 地址:http://www.cnblogs.com/lyhabc/p/4620764.html ...
- vmware里面的名词 vSphere、vCenter Server、ESXI、vSphere Client
vmware里面的名词 vSphere.vCenter Server.ESXI.vSphere Client vSphere.vCenter Server.ESXI.vSphere Client VS ...
- JS核心系列:浅谈 call apply 与 bind
在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...
- Python的单元测试(二)
title: Python的单元测试(二) date: 2015-03-04 19:08:20 categories: Python tags: [Python,单元测试] --- 在Python的单 ...
- javascript表单的Ajax 提交插件的使用
Ajax 提交插件 form.js 表单的下载地址:官方网站:http://malsup.com/jquery/form/ form.js 插件有两个核心方法:ajaxForm()和ajaxSubmi ...
- 要想提高PHP的编程效率,你必须知道的要点
1.当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数.此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储 ...
- PHP获取客户端IP
/** * 获取客户端IP */ function getClientIp() { $ip = 'unknown'; $unknown = 'unknown'; if (isset($_SERVER[ ...
- Entity Framework 教程——Entity Framework中的实体类型
Entity Framework中的实体类型 : 在之前的章节中我们介绍过从已有的数据库中创建EDM,它包含数据库中每个表所对应的实体.在EF 5.0/6.0中,存在POCO 实体和动态代理实体两种. ...
- Android—基于微信开放平台v3SDK,开发微信支付填坑。
接触微信支付之前听说过这是一个坑,,,心里已经有了准备...我以为我没准跳坑出不来了,没有想到我填上了,调用成功之后我感觉公司所有的同事都是漂亮的,隔着北京的大雾霾我仿佛看见了太阳~~~好了,装逼结束 ...