【问题标题】:NSClassFromString() always returns nilNSClassFromString() 总是返回 nil
【发布时间】:2014-08-25 13:26:07
【问题描述】:

尽管ListCell 是一个有效的类,但下面的代码会打印出nil

var lCellClass : AnyClass! = NSClassFromString("ListCell");

println(lCellClass);

文档说方法返回

aClassName 命名的类对象,如果当前没有加载该名称的类,则为 nil。如果 aClassNamenil,则返回 nil

我还尝试获取当前视图控制器的NSClassFromString(),该视图控制器已加载但仍获取nil

可能是什么问题?

更新: 即使尝试这样做NSClassFromString("Array") 我仍然得到nil

【问题讨论】:

  • "即使尝试这样做 NSClassFromString("Array") 我仍然得到 nil" Array 是一个结构,而不是一个类。

标签: ios xcode ios7 xcode5 swift


【解决方案1】:

NSClassFromString 函数确实适用于(纯和 Objective-C 派生的)swift 类,但前提是您使用完全限定名称。

例如,在一个名为 MyApp 的模块中,有一个名为 Person 的纯 swift 类:

let personClass: AnyClass? = NSClassFromString("MyApp.Person")

模块名称由“产品模块名称”(PRODUCT_MODULE_NAME) 构建设置定义,通常与您的目标名称相同(应用了一些规范化,例如删除空格)。

这是非典型的,但如果您正在加载的类在当前模块中,并且您在编译时不知道模块名称,例如因为代码被编译为多个目标的一部分,您可以动态查找包名称,通常对应于模块名称:

let moduleName = Bundle.main.infoDictionary!["CFBundleName"] as! String
let personClass: AnyClass? = NSClassFromString(moduleName + "." + "Person")

我不建议这样做,除非你在编译时真的不知道。

请参阅Using Swift With Cocoa and Objective-C 中的在 Objective-C API 中使用 Swift 类名了解更多信息。

【讨论】:

  • 有趣!谢谢你。
  • 这就是我如此喜欢的原因!!
  • +1 只是好奇它在任何地方都有这样的记录吗?
  • 目前没有,请在bugreport.apple.com提交有关 swift 文档的错误报告
  • 在您的示例中,“MyApp”将是目标名称,而不是项目名称。因此,“MyCustomClass”的通用示例类似于:NSClassFromString(Bundle.main.infoDictionary!["CFBundleName"] as! String + "." + "MyCustomClass")
【解决方案2】:

也可以在 Objective-C 中为符号指定一个名称,它通过使用 @objc 注释省略了 Objective-C 中的命名空间。如果您更喜欢使用不带模块的名称,只需使用相同的类名:

@objc(Foobar)
class Foobar{

}

NSClassFromString("Foobar") 将返回类 Foobar。

【讨论】:

  • 事实上,这是最相关的答案。谢谢。
  • 在使用NSClassFromString 时,您不应该仅仅为了减少输入而这样做。您失去了命名空间的所有好处。您不是“定义[ing] swift 类的命名空间”,而是删除所有命名空间。
  • Objective C 现在支持命名空间吗?
  • 没有。它从来没有它永远不会。添加它们后,您将获得使用 JackLawrence 的配方进行元编程的快速而脆弱的方式。
【解决方案3】:

这可能是你的类没有从 NSObject 扩展的问题。默认情况下,swift没有超类。

【讨论】:

    【解决方案4】:

    例如:

    仅以 UIViewController 为例,

    func getVc(from stringName: String) -> UIViewController? {
        let appName = Bundle.main.infoDictionary!["CFBundleName"] as! String
        guard let vc = NSClassFromString(appName + "." + stringName) as? UIViewController.Type else {
            return nil
        }
        return vc.init()
    }
    

    如果您的应用名称包含“-”或数字,只需将它们替换为“_”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-28
      • 2015-03-05
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多