iOS runtime之元素认知
Posted xiaoxiaobukuang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS runtime之元素认知相关的知识,希望对你有一定的参考价值。
一、什么是runtime
简而言之,Objective-C
Runtime
是一个将C
语言转化为面向对象语言的扩展。
我们将C++
和Objective
进行对比,虽然C++
和Objective-C
都是在C
的基础上加入面向对象的特性扩充而成的程序设计语言,但二者实现的机制差异很大。C++
是基于静态类型,而Objective-C
是基于动态运行时类型。也就是说用C++
编写的程序编译时就直接编译成了可令机器读懂的机器语言;用Objective-C
编写的程序不能直接编译成可令机器读懂的机器语言,而是在程序运行的时候,通过Runtime
把程序转为可令机器读懂的机器语言。Runtime
是Objective
不可缺少的重要一部分。
Runtime
其实有两个版本: “modern
” 和 “legacy
”。我们现在用的 Objective-C 2.0
采用的是现行 (Modern
) 版的 Runtime
系统,只能运行在 ios
和 macOS 10.5
之后的 64
位程序中。而 macOS
较老的32
位程序仍采用 Objective-C 1
中的(早期)Legacy
版本的 Runtime
系统。这两个版本最大的区别在于当你更改一个类的实例变量的布局时,在早期版本中你需要重新编译它的子类,而现行版就不需要。
runtime
是一个c
和汇编
写的动态库,它就像一个小小的系统,将OC和C紧密关联,这个系统主要做两件事 :
- 1、封装C语言的结构体和函数,让开发者在运行时创建、检查或者修改类、对象和方法等等。
- 2、传递消息,找出方法的最终执行代码。
- 1、无参数
OC定义方法
[receiver message]
runtime转化C语言的代码:
objc_msgSend(receiver, selector)
- 2、有参数
OC定义方法
[receiver message:arg1 ...]
runtime转化C语言的代码:
objc_msgSend(receiver, selector, arg1, arg2, ...)
- 3、多方法
OC定义方法
NSObject *object = [[NSObject alloc] init];
runtime转化C语言的代码:
objc_msgSend(objc_msgSend([NSObject class],@selector(alloc)),@selector(init));
二、与runtime交互
bjc
从三种不同的层级上与 Runtime
系统进行交互,分别是:
- 通过
Objective-C
源代码 - 通过
Foundation
框架的NSObject
类定义的方法 - 通过对
runtime
函数的直接调用。
1、Objective-C源代码
编写OC
代码,程序在运行时,runtime
会自动将OC
转化成C
语言代码。
2、NSObject的方法
Cocoa
中大多数类都继承于NSObject
类,也就自然继承了它的方法。最特殊的例外是NSProxy
,它是个抽象超类,它实现了一些消息转发有关的方法,可以通过继承它来实现一个其他类的替身类或是虚拟出一个不存在的类。
有的NSObject
中的方法起到了抽象接口的作用,比如description
方法需要你重载它并为你定义的类提供描述内容。NSObject
还有些方法能在运行时获得类的信息,并检查一些特性,比如class返回对象的类;isKindOfClass:
和isMemberOfClass:
则检查对象是否在指定的类继承体系中;respondsToSelector:
检查对象能否响应指定的消息;conformsToProtocol:
检查对象是否实现了指定协议类的方法;methodForSelector:
则返回指定方法实现的地址。
3、Runtime的函数
Runtime
系统是一个由一系列函数和数据结构组成,具有公共接口的动态共享库。头文件存放于/usr/include/objc
目录下。许多函数允许你用纯C
代码来重复实现 Objc
中同样的功能。虽然有一些方法构成了NSObject
类的基础,但是你在写 Objc
代码时一般不会直接用到这些函数的,除非是写一些 Objc
与其他语言的桥接或是底层的debug
工作。
三、Runtime元素认知
objc_msgSend:方法,它的真身是这样的:
id objc_msgSend ( id self, SEL op, ... );
1、objc_object
objc_msgSend
第一个参数类型为id
,它是一个指向类实例的指针:
// objc-private.h
typedef struct objc_object *id;
objc_object
定义如下:
// objc-private.h
struct objc_object
private:
isa_t isa;
2、objc_class
// objc-private.h
typedef struct objc_class *Class;
objc_class
定义如下:
//objc-runtime-new.h
struct objc_class : objc_object
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
3、isa_t
isa的指向
- 关于对象,其指向类对象;
- 关于类对象,其指向元类对象;
4、cache_t
- 用于快速查找方法执行函数
- 是可增量扩展的哈希表结构
- 是局部性原理的最佳应用
cache_t
的定义如下:
//objc-runtime-new.h
struct cache_t
static bucket_t *emptyBuckets();
struct bucket_t *buckets();
mask_t mask();
mask_t occupied();
void incrementOccupied();
void setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask);
void initializeToEmpty();
unsigned capacity();
bool isConstantEmptyCache();
bool canBeFreed();
;
5、class_data_bits_t
class_data_bits_t
主要是对class_rw_t
的封装class_rw_t
代表了类相关的读写
信息、对class_ro_t
的封装class_ro_t
代表了类相关的只读
信息
class_data_bits_t
定义如下:
//objc-runtime-new.h
struct class_data_bits_t
// Values are the FAST_ flags above.
uintptr_t bits;
public:
class_rw_t* data() const
return (class_rw_t *)(bits & FAST_DATA_MASK);
const class_ro_t *safe_ro()
class_rw_t *maybe_rw = data();
if (maybe_rw->flags & RW_REALIZED)
// maybe_rw is rw
return maybe_rw->ro();
else
// maybe_rw is actually ro
return (class_ro_t *)maybe_rw;
;
①、class_rw_t
//objc-runtime-new.h
struct class_rw_t
public:
const class_ro_t *ro() const
auto v = get_ro_or_rwe();
if (slowpath(v.is<class_rw_ext_t *>()))
return v.get<class_rw_ext_t *>()->ro;
return v.get<const class_ro_t *>();
void set_ro(const class_ro_t *ro)
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>())
v.get<class_rw_ext_t *>()->ro = ro;
else
set_ro_or_rwe(ro);
const method_array_t methods() const
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>())
return v.get<class_rw_ext_t *>()->methods;
else
return method_array_tv.get<const class_ro_t *>()->baseMethods();
const property_array_t properties() const
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>())
return v.get<class_rw_ext_t *>()->properties;
else
return property_array_tv.get<const class_ro_t *>()->baseProperties;
const protocol_array_t protocols() const
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>())
return v.get<class_rw_ext_t *>()->protocols;
else
return protocol_array_tv.get<const class_ro_t *>()->baseProtocols;
;
②、class_ro_t
//objc-runtime-new.h
struct class_ro_t
const char * name;
method_list_t * baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
method_list_t *baseMethods() const
return baseMethodList;
;
6、method_t
method_t
的定义如下:
struct method_t
SEL name;
const char *types;
MethodListIMP imp;
struct SortBySELAddress :
public std::binary_function<const method_t&,
const method_t&, bool>
bool operator() (const method_t& lhs,
const method_t& rhs)
return lhs.name < rhs.name;
;
;
①、types
四、总计
以上是关于iOS runtime之元素认知的主要内容,如果未能解决你的问题,请参考以下文章
我所认知的BIOS—> uEFI AHCI Driver AtaAtapiPassThruSupported的局部变量们