OC runtime学习笔记三
来源:互联网 发布:python yield 详解 编辑:程序博客网 时间:2024/05/16 20:27
github Demo: https://github.com/lihei12345/OCRuntimeTest
参考资料:http://blog.csdn.net/colorapp/article/details/43735817
一. Objective-C Associated Objects
Objective-C 不能动态的添加一些属性到对象上,和其他的一些原生支持这点的语言不一样。所以之前你都不得不努力为未来要增加的变量预留好空间。在 Mac OS X 10.6 中,Objective-C 的 Runtime 已经原生的支持这个功能了。涉及的方法主要有三个:
void objc_setAssociatedObject ( id object, const void *key, id value, objc_AssociationPolicy policy );
id objc_getAssociatedObject ( id object, const void *key );
void objc_removeAssociatedObjects ( id object );
示例代码:
@interface NSView (CustomAdditions)
@property(retain) NSImage *customImage;
@end
@implementation NSView (CustomAdditions)
static char img_key; //has a unique address (identifier)
- (NSImage *)customImage {
return objc_getAssociatedObject(self, &img_key);
}
- (void)setCustomImage:(NSImage *)image {
objc_setAssociatedObject(self, &img_key, image, OBJC_ASSOCIATION_RETAIN);
}
@end
二. NSObject的+load和+initialize函数
参考:http://www.cnblogs.com/biosli/p/NSObject_inherit.html
1. +load函数
当类被引用进程序的时候会执行这个函数。在一个程序开始运行之前(在main函数开始执行之前),在库开始被程序加载,load函数就会开始被执行。
我们开发的程序都可以认为是一个库,但是库又不会独立存在(我们的程序还会引用其他库,也可能被其他函数引用),所以库的初始化顺序可以如下:
1. 初始化我们引用的库
2. 执行我们自己库的Objective-C的load函数
3. 执行C++和C的static初始化变量
4. 初始化引用我们库的其他库
关于load的执行
1. 在我们的编写的库中,会有很多类重写load函数,他们之间的执行顺序是不确定的。
2. 当父类和子类都实现load函数时,父类的load函数会被先执行。
3. load函数是系统自动加载的,因此不需要调用父类的load函数,否则父类的load函数会多次执行。
4. 在category中写load函数是不会替换原始类中的load函数的,原始类和Category中的load函数都会被执行,原始类的load会先被执行,再执行category中的load函数。当有多个category都实现了load函数,这几个load函数执行顺序不确定。
2. +initialize函数
当类第一次被执行到的时候这个函数会被执行。如果类包含继承关系,父类的initialize函数会比子类先执行。由于是系统自动调用,也不需要显式的调用父类的initialize,否则父类的initialize会被多次执行。假如这个类放到代码中,而这段代码并没有被执行,这个函数是不会被执行的
3. 将针对于类修改放在intialize中,将针对Category的修改放在load中。但是假如我们是修改系统的类,一般会通过添加Category来添加功能,但是如果修改initialize会导致原生的intialize不会执行,所以放在load中会比较妥当。
三. Category的实现
参考:http://chun.tips/blog/2014/11/06/bao-gen-wen-di-objective[nil]c-runtime(3)[nil]-xiao-xi-he-category/
Category的结构定义:
struct category_t {
const char *name;
classref_t cls;
struct method_list_t *instanceMethods;
struct method_list_t *classMethods;
struct protocol_list_t *protocols;
struct property_list_t *instanceProperties;
};
Category里面的方法的加载过程,找到对应的源代码与方法:
1.打开objc源代码,找到 objc-os.mm, 函数_objc_init为runtime的加载入口,由libSystem调用,进行初始化操作。
2.之后调用objc-runtime-new.mm -> map_images加载map到内存
3.之后调用objc-runtime-new.mm->_read_images初始化内存中的map, 这个时候将会load所有的类,协议还有Category。NSOBject的+load方法就是这个时候调用的
在OC runtime初始化的时候,会load所有的类,协议以及category。在load 所有的 category之后,就开始对category进行处理,实例方法被加入到了当前的类对象中, 类方法被加入到了当前类的Meta Class中 (cls->ISA);
需要注意的点是:
1. 如果使用clang rewrite源文件之后,查看被编译器转换的代码,Category头文件是会被注释掉了,结合category的加载过程,可以了解到,即使没有import category的头文件,也能够成功调用到Category方法
2. runtime加载完成后,Category的原始信息在类结构中将不会存在
0 0
- OC runtime学习笔记三
- OC runtime学习笔记
- OC runtime学习笔记一
- OC runtime学习笔记二
- 【黑马程序员-学习笔记】OC-Runtime
- OC-runtime学习札记
- OC学习Runtime之方法
- OC学习Runtime之补充
- OC学习笔记三---面向对象三大特性
- 学习笔记 - Runtime学习
- iOS学习笔记56(Runtime)-Objective-C Runtime 运行时之三:方法与消息
- OC学习之Runtime之关联对象
- OC学习Runtime之Method swizzling
- OC学习Runtime之协议与分类
- iOS Runtime 学习笔记
- iOS runtime学习笔记
- Cocoa Runtime学习笔记
- Objc Runtime 学习笔记
- 监控flash_recovery_area的使用情况
- post processor和aware
- 顶尖电商网站的设计趋势
- 给iOS开发新手送点福利,简述UITextField的属性和用法
- 默染江山——oc之block
- OC runtime学习笔记三
- App Store审核指南中文版(2014.10.11更新)
- python程序员常见的10个错误-python语言
- concurrentHashMap原理
- 20150226 N1
- 中国Azure媒体服务RESTAPI的Endpoint
- /etc/shadow文件介绍
- uva11865 - Stream My Contest 最小树形图+二分
- iOS性能优化