【发布时间】:2017-05-02 21:38:16
【问题描述】:
苹果的解释是
objc_getClass与objc_lookUpClass的不同之处在于,如果类未注册,objc_getClass会调用类处理程序回调,然后再次检查该类是否已注册。objc_lookUpClass不调用类处理程序回调。
但我不太了解“类处理程序回调”。你能更详细地解释一下吗?也希望有一些代码能显示出它们的不同,非常感谢!
【问题讨论】:
苹果的解释是
objc_getClass与objc_lookUpClass的不同之处在于,如果类未注册,objc_getClass会调用类处理程序回调,然后再次检查该类是否已注册。objc_lookUpClass不调用类处理程序回调。
但我不太了解“类处理程序回调”。你能更详细地解释一下吗?也希望有一些代码能显示出它们的不同,非常感谢!
【问题讨论】:
在“旧版”Objective-C 运行时(在 x86_64 之前的 macOS 上使用,之前由 iPhone 模拟器使用——但在 Apple 操作系统的最新版本中没有使用),应用程序可以使用以下方式注册“类处理程序回调”这个函数(在<objc/runtime.h>):
OBJC_EXPORT void
objc_setClassHandler(int (* _Nullable )(const char * _Nonnull));
这允许调用者注册一个函数指针,如果objc_getClass() 无法找到请求的类,运行时将调用该函数指针。注册的函数可能会通过正在寻找的名称创建一个类(和元类)。当函数返回时,objc_getClass() 会再次尝试获取函数注册的类。
“现代”运行时不存在此功能。
【讨论】:
他们的方法解释在苹果的文档中是模棱两可的。但运行时代码在Apple Opensource 中打开。 根据运行时的开源,我发现他们两个方法实现如下:
Class objc_getClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName, NO, YES);
}
Class objc_lookUpClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, NO class handler
return look_up_class(aClassName, NO, NO);
}
两个方法都调用look_up_class方法,最后一个参数不同。在look_up_class 内部,最后一个拖曳参数未使用。
所以,总而言之,我认为objc_getClass 和objc_lookUpClass 都一样。
Class
look_up_class(const char *name,
bool includeUnconnected __attribute__((unused)),
bool includeClassHandler __attribute__((unused)))
{
if (!name) return nil;
Class result;
bool unrealized;
{
rwlock_reader_t lock(runtimeLock);
result = getClass(name);
unrealized = result && !result->isRealized();
}
if (unrealized) {
rwlock_writer_t lock(runtimeLock);
realizeClass(result);
}
return result;
}
【讨论】: