NSClassFromString为嵌套类返回nil

时间:2017-08-16 11:15:09

标签: ios swift

我想通过使用字符串来实例化一个类,但我遇到了问题。这就是我尝试做的事情:

let aClass = NSClassFromString("MyApp.Outer.Inner") as! SomeProtocol.Type
....
public class Outer {
    public class Inner: SomeProtocol {
        init() {...}
    }
}

崩溃(因为NSClassFromString返回nil

但是那个人在工作:

let aClass = NSClassFromString("MyApp.Inner") as! SomeProtocol.Type
....
public class Inner: SomeProtocol {
    init() {...}
}

没有NSClassFromString适用于嵌套类吗?

背景: 我有很多内心的"我用作模板来创建对象的类(而不是将它们存储在.plist文件中,这有点令人讨厌)。我想将它们封装在一个"外部"让他们更好地组织起来。

感谢您的帮助:)

编辑:我看到的问题似乎是重复的。但那不是一个可行的解决方案:

  

(注意这个片段本身不会运行 - 为了在ObjC运行时注册,必须至少在你的进程中的某个地方引用AB类。这可能就像放置let一样简单=在应用程序的启动代码中的某处。)

我正在使用NSClassFromString执行此方法,因为我想避免为我创建的每个内部类添加太多内容。我不想经常将其添加到我的启动代码中。

1 个答案:

答案 0 :(得分:3)

如果您运行此代码:

import Foundation

class Outer: NSObject {
    class Inner: NSObject {}
}

print(NSStringFromClass(Outer.Inner.self))

您将获得以下内容:

_TtCC8Untitled5Outer5Inner

正如您所看到的,嵌入式类的名称与您期望的名称不同。我相信修改格式也没有文档记录,所以你不能依赖它在未来的Swift版本中不会改变。

如果您需要能够在Objective-C运行时中使用其名称访问类,则可以使用@objc属性为其提供自定义的Objective-C名称。遗憾的是,@objc关键字不允许使用点,但您可以使用下划线获得类似的效果:

class Outer: NSObject {
    @objc (Outer_Inner) class Inner: NSObject {}
}

编辑:我应该澄清一下,即使指定了@objc关键字,内部类仍然需要被Swift代码访问才能用于Objective-C运行时,因此在像{之类的函数之前{1}}会有用。