Runtime

Runtime - Method

2021-07-27  本文已影响0人  ienos

参考文档


Method
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;
}
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
上一篇 下一篇

猜你喜欢

热点阅读