当一个新的 class 添加到运行时时是否可以得到通知? (Objective C)
Is it possible to get notified when a new class is added to the runtime? (Objective C)
Objective-C 运行时允许分别使用 objc_allocateClassPair
和 objc_registerClassPair
动态创建和注册 class 对。当一个新的 class 添加到运行时时是否可以得到通知? (我只关心已注册的 Objective-C classes 如果有帮助,未注册的 classes 将是一个奖励。)
如果无法通知,下一个最有效率的事情是什么?大多数 iOS 设备都有严格的计算限制,因此我的选择有限。如果可能的话,我愿意接受一些运行时黑客攻击。我意识到我可以挂钩 +load
,但这只适用于 NSObject subclasses,而不是纯 Swift classes。
"PureSwiftclasses?但是pureSwiftclasses不是Objective Cclasses!"你说?再想想。尝试使用运行时自省一个纯粹的 Swift class,您会发现它所包含的远比看上去的要多! "How can one end up having a Swift class being added dynamically?" 好吧,我可以加载一个使用 Swift!
的动态框架
自@SpaceDog 询问以来,这是我正在开发的开发人员实用程序。进一步说明:我自己不知道什么时候会调用 objc_allocateClassPair
或 objc_registerClassPair
,因为我的项目是一个库。
简答:否
长答案:有点。
有两种方法可以解决这个问题。遗憾的是,这两者都需要看门狗线程和轮询。
没有您可以 piggy-back 无需重写符号的同步回调。
(当然,如果可以的话,您还有很多其他解决方案)
第一个选项,仅使用 public APIs:您可以随时观察 objc_getClassList
的计数变化。
此解决方案的问题在于,它会将 force-load 所有 class 可以简单地加载到共享 DYLD 缓存中的元素提供给用户 space。这只会发生一次,但这样做会对性能造成相当大的影响。冷启动时间当然不好。
注意:objc_getClassList
的排序顺序不是well-defined(内部依赖unstablehash-table),所以没有好的办法(例如小于 O(N)
storage/time) 来确定具体添加了哪个 class。
第二个选项,可能是更可行的选项,是(ab)使用调试器特定 API gdb_objc_realized_classes
.
这是 NXMapTable
(class 名称(const char *
) 到 Class 指针(又名 objc_class
)。
注意:NXMapTable
不再包含在 public headers 中,因为这是一个非常旧的版本 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
具有 零 thread-safety 保证,因此如果您有多个线程可能注册 classes,您可以 运行 进入问题。
这些解决方案可以让您知道何时添加一个class,但不一定是添加的特定class。
最后,如果您担心内存(因为您可能应该考虑 Foundation 框架本身就有 1500 个 classes),一种选择可能是保留类似于 bloom filter 的已知已注册 classes,然后,当 objc_getClassList
的结果发生变化时,找出哪个 class 没有通过该布隆过滤器,并且您拥有最新注册的 class.
然而,作为一种概率数据结构,你会有漏报——例如如果您的 pointer/name 哈希值不够好,一些 classes 可能会漏掉。
祝你好运。
Objective-C 运行时允许分别使用 objc_allocateClassPair
和 objc_registerClassPair
动态创建和注册 class 对。当一个新的 class 添加到运行时时是否可以得到通知? (我只关心已注册的 Objective-C classes 如果有帮助,未注册的 classes 将是一个奖励。)
如果无法通知,下一个最有效率的事情是什么?大多数 iOS 设备都有严格的计算限制,因此我的选择有限。如果可能的话,我愿意接受一些运行时黑客攻击。我意识到我可以挂钩 +load
,但这只适用于 NSObject subclasses,而不是纯 Swift classes。
"PureSwiftclasses?但是pureSwiftclasses不是Objective Cclasses!"你说?再想想。尝试使用运行时自省一个纯粹的 Swift class,您会发现它所包含的远比看上去的要多! "How can one end up having a Swift class being added dynamically?" 好吧,我可以加载一个使用 Swift!
的动态框架自@SpaceDog 询问以来,这是我正在开发的开发人员实用程序。进一步说明:我自己不知道什么时候会调用 objc_allocateClassPair
或 objc_registerClassPair
,因为我的项目是一个库。
简答:否
长答案:有点。
有两种方法可以解决这个问题。遗憾的是,这两者都需要看门狗线程和轮询。
没有您可以 piggy-back 无需重写符号的同步回调。
(当然,如果可以的话,您还有很多其他解决方案)
第一个选项,仅使用 public APIs:您可以随时观察
objc_getClassList
的计数变化。此解决方案的问题在于,它会将 force-load 所有 class 可以简单地加载到共享 DYLD 缓存中的元素提供给用户 space。这只会发生一次,但这样做会对性能造成相当大的影响。冷启动时间当然不好。
注意:
objc_getClassList
的排序顺序不是well-defined(内部依赖unstablehash-table),所以没有好的办法(例如小于O(N)
storage/time) 来确定具体添加了哪个 class。
第二个选项,可能是更可行的选项,是(ab)使用调试器特定 API
gdb_objc_realized_classes
.这是
NXMapTable
(class 名称(const char *
) 到 Class 指针(又名objc_class
)。注意:
的NXMapTable
不再包含在 public headers 中,因为这是一个非常旧的版本 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
具有 零 thread-safety 保证,因此如果您有多个线程可能注册 classes,您可以 运行 进入问题。
这些解决方案可以让您知道何时添加一个class,但不一定是添加的特定class。
最后,如果您担心内存(因为您可能应该考虑 Foundation 框架本身就有 1500 个 classes),一种选择可能是保留类似于 bloom filter 的已知已注册 classes,然后,当 objc_getClassList
的结果发生变化时,找出哪个 class 没有通过该布隆过滤器,并且您拥有最新注册的 class.
然而,作为一种概率数据结构,你会有漏报——例如如果您的 pointer/name 哈希值不够好,一些 classes 可能会漏掉。
祝你好运。