【问题标题】:Swift 3 - class name/type lookupSwift 3 - 类名/类型查找
【发布时间】:2017-02-18 09:51:49
【问题描述】:

我的应用程序使用了数百个绘图类的子类。 (这些子类是从艺术文件中自动生成的。)

理想情况下,我想加载一些子类的名称,检查这些子类是否实际可用,如果是,则实例化它们。

然而,似乎纯 Swift 中缺少 NSClassFromString 风格的功能意味着我不得不提前向编译器声明我的所有类名。

例如通过非常冗长乏味的 switch 语句获取课程:

func drawingObjectFromClassName(_ className: String) -> SomeDrawingProtocol?
{
    switch className {
        case "foo": return foo()
        case "bar": return bar()
        // etc.

        default:
            print("Warning: no class found for className: ", className)
            return nil
    }
}

但我还想检查是否存在子类(例如“foo”),而不必实例化对象。

可以复制该 switch 语句来执行此操作,但是我需要维护两组相同的键。呸。

因此,一种可能的解决方案是使用查找表。

问题:如果我用我的所有子类名称作为键对字典进行硬编码,values 需要什么语法,以便检索到的值可以被实例化为所需类的对象?感谢您的帮助。

【问题讨论】:

  • 您可以返回foo.self 来获取一个类对象(SomeDrawingProtocol.Type 类型)。

标签: swift dynamic metaprogramming metaclass


【解决方案1】:
protocol P {
    init()
}

extension String : P { }

extension Int : P { }

let types : [String : P.Type] = [
    "str": String.self,
    "int": Int.self
]

if let type = types["int"] {
    let object = type.init()
    assert(object is Int)
}

您现在可以使用所有标准字典操作来检查事物是否存在,根据需要转换您提取的类型等。

我在上面的示例中定义了协议,以便有一个通用的初始化程序(这可能是您在大多数情况下需要的),但您可以简单地使用 Any.Type 并在需要时使用 as Int.Type 转换类型.

【讨论】:

  • 谢谢格雷格。非常感谢!一旦我将 init() 调用添加到原型中,并告诉自动机将所需的 init() 调用添加到每个子类,它就会像宣传的那样工作。干杯!
  • @Womble(不确定您是否这样做)如果所有内容都是SomeDrawingProtocol 类型,您可以只使用SomeDrawingProtocol.Type 作为字典元素的类型,只要它声明了一些初始化器 all你的类实现。
  • 谢谢格雷格。我确实使用 SomeDrawingProtocol.Type 作为字典的类型。是那个 init() 把我扔了... Xcode 很有帮助(?)试图让我实例化 type(of:)... init。 :) 欢呼。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
相关资源
最近更新 更多