Runtime - Method
2021-07-27 本文已影响0人
ienos
参考文档
![](https://img.haomeiwen.com/i1929662/b65e3c3762acc1b0.png)
struct method_t {
SEL name;
const char *types;
IMP 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; }
};
};
源码阅读
1. 寻找 IMP(函数指针)
IMP lookUpImpOrForward(Class cls, SEL sel, id inst,
bool initialize, bool cache, bool resolver)
{
Class curClass;
IMP imp = nil;
Method meth;
bool triedResolver = NO;
runtimeLock.assertUnlocked();
// 获取缓存中的 imp
if (cache) {
imp = cache_getImp(cls, sel);
if (imp) return imp;
}
// realizedClass if !cls->isRealized()
if (!cls->isRealized()) {
rwlock_writer_t lock(runtimeLock);
realizeClass(cls);
}
// initialize if !cls->isInitialized()
if (initialize && !cls->isInitialized()) {
_class_initialize (_class_getNonMetaClass(cls, inst));
}
retry:
runtimeLock.read();
// Ignore GC selectors
if (ignoreSelector(sel)) {
imp = _objc_ignored_method;
cache_fill(cls, sel, imp, inst);
goto done;
}
// Try this class's cache.
imp = cache_getImp(cls, sel);
if (imp) goto done;
// 获取 class 中的 method_list
meth = getMethodNoSuper_nolock(cls, sel);
if (meth) {
log_and_fill_cache(cls, meth->imp, sel, inst, cls);
imp = meth->imp;
goto done;
}
// Loop 直到 superclass = nil
curClass = cls;
while ((curClass = curClass->superclass)) {
// Superclass cache.
imp = cache_getImp(curClass, sel);
if (imp) {
if (imp != (IMP)_objc_msgForward_impcache) {
log_and_fill_cache(cls, imp, sel, inst, curClass);
goto done;
}
else {
// Found a forward:: entry in a superclass.
// Stop searching, but don't cache yet; call method
// resolver for this class first.
break;
}
}
// 获取 Superclass 的 method_list
meth = getMethodNoSuper_nolock(curClass, sel);
if (meth) {
log_and_fill_cache(cls, meth->imp, sel, inst, curClass);
imp = meth->imp;
goto done;
}
}
// 依旧没有找到则,尝试 resolver method
if (resolver && !triedResolver) {
runtimeLock.unlockRead();
_class_resolveMethod(cls, sel, inst);
triedResolver = YES;
goto retry;
}
// 方法没有实现且不支持 resolver,尝试开始转发
imp = (IMP)_objc_msgForward_impcache;
cache_fill(cls, sel, imp, inst);
done:
runtimeLock.unlockRead();
assert(!(ignoreSelector(sel) && imp != (IMP)&_objc_ignored_method));
assert(imp != _objc_msgSend_uncached_impcache);
return imp;
}
- 第一步: 从 class cache 中找 IMP
- 第二步: 从 objc_class->class_rw_t->methods 中找 IMP
- 第三步: Loop (curClass = curClass->superclass) 直到 superClass = nil, 从 curClass cache 中找 IMP,如果找不到,从 curClass->class_rw_t->methods 中找 IMP
- 第四步: 如果寻找不到 IMP,返回
_objc_msgSend_uncached_impcache
转发函数指针
2. Method->types 类型编码
编译器对方法的返回值和参数进行编码,例如:
char *buf1 = @encode(int **);
type encodings | 描述 |
---|---|
c | A char |
i | An int |
s | A short |
l | A longl is treated as a 32-bit quantity on 64-bit programs. |
q | A long long |
C | An unsigned char |
I | An unsigned int |
S | An unsigned short |
L | An unsigned long |
Q | An unsigned long long |
f | A float |
d | A double |
B | A C++ bool or a C99 _Bool |
v | A void |
* | A character string (char *) |
@ | An object (whether statically typed or typed id) |
# | A class object (Class) |
: | A method selector (SEL) |
[array type] | An array |
{name=type...} | A structure |
(name=type...) | A union |
bnum | A bit field of num bits |
^type | A pointer to type |
? | An unknown type (among other things, this code is used for function pointers) |
type encodings | 关键字 |
---|---|
r | const |
n | in |
N | inout |
o | out |
O | bycopy |
R | byref |
V | oneway |