不明白NSClassFromString如何用于条件调用

时间:2012-12-10 23:43:29

标签: ios

我的项目中有一个测试类,在开发阶段就在那里,但是会针对app store build编译出来。

我在几本书中读过NSClassFromString可以用来确定一个类是否存在,例如:

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

然而,在我的项目中付诸实践之后,我发现我在目标中遇到链接错误,我删除了包含SomeClass的源文件。

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

1 个答案:

答案 0 :(得分:6)

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

为了使编译器成功通过像[SomeClass someMethod]这样的静态引用,它需要链接一些内容。

你是正确的,当你链接到像Foundation这样的东西时,这个机制是有效的,Apple会在那里添加一个额外的类,比如检查NSJSONSerialization是否存在。

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

Apple实际上已经略微修改了库的存储方式,并且正在转换为允许使用if([TWRequest class])或其他任何内容来代替弱链接的显式NSClassFromString

但是,在您的情况下,您似乎想要链接到静态库或不链接到它?那么类在运行时是否可用,但链接器可能也可能不可见?

在这种情况下,您只需要避免对元类的文字引用。所以你可以这样做:

Class someClassMetaClass = NSClassFromString(@"SomeClass");

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

只要头文件可见,编译器就会很高兴允许你为指针指定SomeClass类型(因为它不会进入二进制文件)并且能够建议通常的自动完成和针对已发布界面的警告。只需确保始终通过指向运行时而不是直接从运行时获取的Class的指针来解决元类。这样,链接器就无需跟进。