Objective-C运行时允许分别使用objc_allocateClassPair
和objc_registerClassPair
动态创建和注册类对。将新类添加到运行时是否可以获得通知? (我只关注已注册的Objective-C课程,如果有帮助,未注册的课程将是奖金。)
如果无法收到通知,那么下一个最有效的方法是什么?大多数iOS设备都有严格的计算限制,因此我的选择有限。如果可以的话,我会对运行时的hackery开放。我意识到我可以挂钩+load
,但这只适用于NSObject子类,而不是纯粹的Swift类。
" Pure Swift课程?但纯Swift类不是Objective C类!"你说?再想想。尝试使用运行时内省一个纯粹的Swift类,你会发现它有更多的东西而不是眼睛! "如何最终动态添加Swift类?"好吧,我可以加载一个使用Swift的动态框架!
由于@SpaceDog问道,这是我正在开发的开发人员实用程序。有关进一步说明:我自己不知道何时调用objc_allocateClassPair
或objc_registerClassPair
,因为我的项目是一个库。
答案 0 :(得分:3)
有两种方法可以解决这个问题。遗憾的是,这两者都需要看门狗线程和民意调查。
在没有重写符号的情况下,没有同步回调可以背负。
(当然,如果这是一个选项,你有很多其他的解决方案)
第一个选项,仅使用公共API:您可以随时查看objc_getClassList
的计数是否会发生变化。
此解决方案的问题在于它会将可能只是加载到共享DYLD缓存中的所有类强制加载到用户空间中。这只会发生一次,但这样做会有相当大的性能影响。当然不适合冷启动时间。
注意:objc_getClassList
的排序顺序没有明确定义(内部依赖于不稳定的哈希表),因此没有好办法(例如,存储/时间小于O(N)
)确定具体添加了哪个类。
第二个选项,也许是更可行的选项,是(ab)使用调试器特定的API gdb_objc_realized_classes
。
这是类名(NXMapTable
)到类指针(又名。const char *
)的objc_class
(在objective-c运行时内部使用的超老哈希表实现)。
注意:NXMapTable
已不再位于公共标题中,因为它是一个非常旧版本的OSX(10.4?),因此您需要从Apple Open Source获取最新版本的maptable.h
。
使用示例:
#import "maptable.h"
extern NXMapTable *gdb_objc_realized_classes;
int main() {
printf("Realized classes: %d\n", NXCountMapTable(gdb_objc_realized_classes));
Class superClass = [NSObject class];
Class myKls = objc_allocateClassPair(superClass, "TestClass", 0);
objc_registerClassPair(myKls);
printf("Realized classes: %d\n", NXCountMapTable(gdb_objc_realized_classes));
}
另请注意:gdb_objc_realized_classes
具有零线程安全保证,因此如果您有多个线程可能注册类,则可能会遇到问题。
这些解决方案可让您在添加类时了解,但不一定是已添加的特定类。
最后,如果您担心内存(因为您可能应该考虑单独使用Foundation框架中有1500个类),一个选项可能是保持数据结构类似于已知注册的bloom filter类,然后,当objc_getClassList
的结果发生变化时,找出哪个类没有通过那个布隆过滤器并且你有最新的注册类。
但是,作为概率数据结构,您将有误报 - 例如如果您的指针/名称哈希值不够好,某些类可能会破裂。
祝你好运。