在运行时源代码(objc4-723
版本)中,将消息发送到对象时,运行时可以通过两种方式搜索方法:
/***********************************************************************
* getMethodNoSuper_nolock
* fixme
* Locking: runtimeLock must be read- or write-locked by the caller
**********************************************************************/
static method_t *search_method_list(const method_list_t *mlist, SEL sel) {
int methodListIsFixedUp = mlist->isFixedUp();
int methodListHasExpectedSize = mlist->entsize() == sizeof(method_t);
if (__builtin_expect(methodListIsFixedUp && methodListHasExpectedSize, 1)) {
return findMethodInSortedMethodList(sel, mlist);
} else {
// Linear search of unsorted method list
for (auto& meth : *mlist) {
if (meth.name == sel) return &meth;
}
}
#if DEBUG
// sanity-check negative results
if (mlist->isFixedUp()) {
for (auto& meth : *mlist) {
if (meth.name == sel) {
_objc_fatal("linear search worked when binary search did not");
}
}
}
#endif
return nil;
}
运行系统将判断方法列表是否已排序,然后选择线性搜索还是二进制搜索。
如果方法列表已排序,则显然二进制搜索更好,否则应为线性搜索。
所以我的问题是,在什么情况下将对一个类中的方法进行排序?
何时对它们进行排序?是谁的?
答案 0 :(得分:0)
看看isFixedUp
标志何时设置为true。
https://opensource.apple.com/source/objc4/objc4-706/runtime/objc-runtime-new.mm.auto.html
基本上,当一个进程启动时,dyld和运行时都具有“修复”阶段,在该阶段中,它们将符号绑定在一起,优化了很多东西,否则为应用程序准备运行。
ObjC的修复阶段可以优化方法列表的布局,以加快后续查找的速度。特别是,fixup将确保每个选择器都是唯一的;也就是说,一个对象的layoutSubviews
方法的选择器将与另一个对象的选择器按位相同,而不仅仅是指向同一char*
的两个副本。它还可以对列表进行排序,这也可以使查找变得更快。
一旦修复,方法查找就可以沿着快速路径进行(调用findMethodInSortedMethodList
)。如果未解决,则运行时将进行线性搜索(如该代码所示)。