1. 基本数据结构
// 方法结构
struct method_t {
SEL name; // 方法名
const char *types; // 类型编码
IMP imp; // 方法实现
};
// 类结构
struct objc_class {
Class isa;
Class superclass;
cache_t cache; // 方法缓存
class_data_bits_t bits; // 类的方法、属性等信息
};
// 方法缓存
struct cache_t {
struct bucket_t *_buckets; // 散列表
mask_t _mask; // 容量掩码
mask_t _occupied; // 已使用数量
};
2. 消息发送流程
2.1 基本流程
// 消息发送入口
id objc_msgSend(id self, SEL _cmd, ...) {
if (!self) return nil;
// 1. 查找方法缓存
IMP imp = cache_getImp(self->isa, _cmd);
if (imp) return imp(self, _cmd, ...);
// 2. 完整查找流程
return _objc_msgSend_uncached(self, _cmd, ...);
}
2.2 方法查找
IMP lookUpImpOrForward(id obj, SEL sel) {
Class cls = obj->getIsa();
// 1. 查找当前类的方法
Method method = class_getInstanceMethod(cls, sel);
if (method) {
// 加入缓存
cache_fill(cls, sel, method->imp);
return method->imp;
}
// 2. 查找父类方法
for (Class tcls = cls->superclass; tcls; tcls = tcls->superclass) {
method = class_getInstanceMethod(tcls, sel);
if (method) {
cache_fill(cls, sel, method->imp);
return method->imp;
}
}
// 3. 动态方法解析
if (resolveInstanceMethod(cls, sel)) {
return lookUpImpOrForward(obj, sel);
}
// 4. 消息转发
return _objc_msgForward;
}
3. 方法缓存机制
3.1 缓存结构
struct cache_t {
// 缓存桶
struct bucket_t {
SEL _sel; // 方法名
IMP _imp; // 方法实现
} *_buckets;
// 查找方法
IMP imp(SEL sel) {
bucket_t *b = buckets();
mask_t m = mask();
mask_t begin = cache_hash(sel, m);
mask_t i = begin;
do {
if (b[i].sel() == sel) {
return b[i].imp();
}
} while ((i = cache_next(i, m)) != begin);
return nil;
}
};
3.2 缓存优化
// 缓存哈希算法
static inline mask_t cache_hash(SEL sel, mask_t mask) {
return (mask_t)(uintptr_t)sel & mask;
}
// 缓存扩容
void cache_t::expand() {
uint32_t oldCapacity = capacity();
uint32_t newCapacity = oldCapacity ? oldCapacity * 2 : INIT_CACHE_SIZE;
if (newCapacity > MAX_CACHE_SIZE) {
newCapacity = MAX_CACHE_SIZE;
}
reallocate(oldCapacity, newCapacity);
}
4. 消息转发机制
4.1 动态方法解析
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(someMethod:)) {
class_addMethod(self,
sel,
(IMP)dynamicMethodIMP,
"v@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
4.2 快速转发
- (id)forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(someMethod:)) {
return alternateObject; // 转发给其他对象
}
return [super forwardingTargetForSelector:aSelector];
}
4.3 完整转发
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(someMethod:)) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
if ([alternateObject respondsToSelector:
[anInvocation selector]]) {
[anInvocation invokeWithTarget:alternateObject];
} else {
[super forwardInvocation:anInvocation];
}
}
5. 性能优化
5.1 方法缓存
// 缓存命中检查
static ALWAYS_INLINE IMP cache_getImp(Class cls, SEL sel) {
cache_key_t key = cache_key(sel);
bucket_t *buckets = cls->cache.buckets();
mask_t mask = cls->cache.mask();
bucket_t *bucket = &buckets[key & mask];
if (bucket->key() == key) {
return bucket->imp();
}
return nil;
}
5.2 方法内联
// 编译器优化
static ALWAYS_INLINE id
objc_msgSendSuper2(struct objc_super2 *super, SEL op, ...) {
return ((id (*)(struct objc_super2 *, SEL, ...))objc_msgSendSuper2_fixup)(super, op, ...);
}
6. 特殊情况处理
6.1 nil 消息
if (!self) return nil; // 发送给 nil 的消息返回 nil
6.2 Tagged Pointer
if (objc_isTaggedPointer(obj)) {
// 特殊处理 Tagged Pointer
return objc_msgSend_tagged(obj, sel, ...);
}
7. 线程安全
7.1 缓存更新
static void cache_fill(Class cls, SEL sel, IMP imp) {
cache_t *cache = &cls->cache;
cache->mutex.lock();
// 更新缓存
cache->insert(sel, imp);
cache->mutex.unlock();
}
7.2 方法添加
static IMP addMethod(Class cls, SEL name, IMP imp, const char *types) {
mutex_locker_t lock(runtimeLock);
IMP result = nil;
if (addMethodNoLock(cls, name, imp, types, &result)) {
// 更新方法缓存
flushCaches(cls);
}
return result;
}
这个消息机制设计的关键点:
- 高效的方法查找
- 灵活的消息转发
- 优秀的缓存策略
- 完善的线程安全
- 特殊情况的处理
这些特性使得 Objective-C 的消息机制既灵活又高效。