5

我的项目中有一个测试类,它在开发阶段就在那里,但会为应用商店构建而编译出来。

我在几本书中读过 NSClassFromString 可用于通过示例代码确定一个类是否存在,例如:

if (NSClassFromString(@"SomeClass") != nil)
{
[SomeClass someMethod];
}
else
{
code not using SomeClass
}

但是,在我的项目中将其付诸实践后,我发现我在删除包含 SomeClass 的源文件的目标时遇到了链接错误。

因此,我的结论是,这种确定类存在/不存在的机制仅在该类位于您使用其他类的库或源文件中时才有用(提及此技术的书籍中缺少该细节)。还是我错过了什么?

4

1 回答 1

6

NSClassFromString在运行时搜索命名类。事实上,它将确定该类是否存在。

为了让编译器成功地获得过去的静态引用,就像[SomeClass someMethod]它需要链接的东西一样。

您是对的,因此当您链接到 Foundation 之类的东西时,该机制会起作用,Apple 会在那里添加一个额外的类,例如检查是否NSJSONSerialization存在。

如果您对可能存在或不存在的框架进行弱链接,它也可以工作。因此,例如,您可以对 Twitter.framework 进行弱链接并使用[TWRequest alloc] .... 您仍然可以在根本没有 Twitter 框架的 iOS 4 上构建和部署。

苹果实际上已经稍微修改了库的存储方式,并且正在过渡到允许if([TWRequest class])或使用任何东西来代替显式的NSClassFromString弱链接。

但是,在您的情况下,听起来您想要链接到静态库还是不链接到它?因此,该类在运行时可能可用也可能不可用,但链接器也可能可见或不可见?

在这种情况下,您只需要避免对元类的字面引用。因此,您可以执行以下操作:

Class someClassMetaClass = NSClassFromString(@"SomeClass");

if(someClassMetaClass)
{
    SomeClass *instance = [[someClassMetaClass alloc] init];
    /* ... */
}

只要头文件可见,编译器就会很乐意允许您指定SomeClass指针的类型(因为无论如何它都不会进入二进制文件),并且能够针对已发布的接口建议通常的自动完成和警告。只要确保您始终通过指向Class您从运行时而不是直接获得的指针来寻址元类。这样,链接器就没有什么需要跟进的了。

于 2012-12-11T00:00:39.140 回答