方法是类的一个重要的组成部分,在Objective-C,方法被分为对象方法、类方法。

他们除了-/+不同之外,其他的都相同;他们在内存中是对象方法存储在类对象中,类方法存储在元类中。

那么方法在源码中是什么样子的呢?

#if __has_feature(ptrauth_calls)

#if !__arm64__
#error ptrauth other than arm64e is unimplemented
#endif
// Method lists use process-independent signature for compatibility.
using MethodListIMP = IMP __ptrauth_objc_method_list_imp;
#else
using MethodListIMP = IMP;
#endif

struct method_t {
    struct big {
        SEL name;
        const char *types;
        MethodListIMP imp;
    };
    big &big() const {
        ASSERT(!isSmall());
        return *(struct big *)this;
    }

    SEL name() const {
        if (isSmall()) {
            return (small().inSharedCache()
                    ? (SEL)small().name.get()
                    : *(SEL *)small().name.get());
        } else {
            return big().name;
        }
    }
    const char *types() const {
        return isSmall() ? small().types.get() : big().types;
    }
    IMP imp(bool needsLock) const {
        if (isSmall()) {
            IMP imp = remappedImp(needsLock);
            if (!imp)
                imp = ptrauth_sign_unauthenticated(small().imp.get(),
                                                   ptrauth_key_function_pointer, 0);
            return imp;
        }
        return big().imp;
    }
};

在mehtod_t中一个内部struct big 描述了方法在内存中的描述。

#if !__arm64__
#error ptrauth other than arm64e is unimplemented
#endif
// Method lists use process-independent signature for compatibility.
using MethodListIMP = IMP __ptrauth_objc_method_list_imp;
#else
using MethodListIMP = IMP;
#endif 

struct big {
	SEL name; // 函数名
	const char *types; // 编码(返回值类型、参数类型)
	MethodListIMP imp; // 指向函数的指针(函数地址)
};

我们可以打印内存中方法,看看他是啥样子的

Untitled

IMP

IMP的实现:

**typedef** **id** **_Nullable** (***IMP**)(**id** **_Nonnull**, **SEL** **_Nonnull**, ...);

SEL

代表方法\函数名,一般叫做选择器,底层结构跟char *类似