简体   繁体   English

NSClassFromString为嵌套类返回nil

[英]NSClassFromString returning nil for nested class

I want to instantiate a class by using a string but I'm having problems. 我想通过使用字符串来实例化一个类,但我遇到了问题。 That's what I try to do: 这就是我尝试做的事情:

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

That's crashing (because NSClassFromString returns nil 那崩溃了(因为NSClassFromString返回nil

But that's working: 但那是有效的:

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

Doesn't NSClassFromString work for nested classes? NSClassFromString用于嵌套类吗?


Background: I have many "inner" classes that I use as templates to create objects (instead of storing them in .plist files, which is kind of annoying). 背景:我有许多“内部”类,我用它们作为模板来创建对象(而不是将它们存储在.plist文件中,这有点烦人)。 I want to encapsulate them in an "Outer" class to have them better organised. 我想将它们封装在一个“外部”类中,以使它们更好地组织起来。

Thanks for any help :) 谢谢你的帮助 :)

EDIT: I saw the question that this seems to be a duplicate of. 编辑:我看到这个似乎是重复的问题。 But that's not a viable solution: 但这不是一个可行的解决方案:

(Note this snippet won't run by itself -- the class AB has to be referenced at least once somewhere in your process in order to be registered with the ObjC runtime. This could be as simple as putting let t = ABself somewhere in your app's startup code.) (注意这个片段本身不会运行 - 为了在ObjC运行时注册,必须至少在你的进程中的某个地方引用AB类。这可能就像把t = ABself放在你的某个地方一样简单应用程序的启动代码。)

I'm doing this approach with NSClassFromString because I want to avoid adding too much stuff for every inner class I create. 我正在使用NSClassFromString进行这种方法,因为我想避免为我创建的每个内部类添加太多东西。 I don't want to constantly add this to my startup code. 我不想经常将它添加到我的启动代码中。

If you run this code: 如果您运行此代码:

import Foundation

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

print(NSStringFromClass(Outer.Inner.self))

You will get something like the following: 您将获得以下内容:

_TtCC8Untitled5Outer5Inner

As you can see, embedded classes have their names mangled differently from how you'd expect. 正如您所看到的,嵌入式类的名称与您期望的名称不同。 I believe the mangling format is undocumented, as well, so you can't rely on this not changing in some future Swift release. 我相信修改格式也没有文档记录,所以你不能依赖这个在未来的Swift版本中不会改变。

If you need to be able to access a class using its name in the Objective-C runtime, you can use the @objc attribute to give it a custom Objective-C name. 如果您需要能够在Objective-C运行时中使用其名称访问类,则可以使用@objc属性为其提供自定义的Objective-C名称。 Unfortunately, the @objc keyword doesn't allow dots, but you can use underscores for a similar effect: 不幸的是, @objc关键字不允许使用点,但您可以使用下划线来获得类似的效果:

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

EDIT: I should clarify that even with the @objc keyword specified, the inner class will still need to be accessed by Swift code before it will be available to the Objective-C runtime, and thus before functions like NSClassFromString() will work. 编辑:我应该澄清,即使指定了@objc关键字,内部类仍然需要被Swift代码访问才能用于Objective-C运行时,因此在NSClassFromString()类的函数可以工作之前。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM