如何使用反射在Swift中获取所有类的初始化程序

3
我在尝试从Swift类中获取所有初始化程序的签名。 初始化器可以镜像,我可以像下面的代码一样找到签名。
enum MessageType {
    case say
    case shout
    case wisper
}

class Message {
    var text = ""
    var type : MessageType = .say
    init(text: String, type: MessageType) {
        self.type = type
        self.text = text
    }
    init(text: String) {
        self.text = text
    }
}

let firstInit = Message.init(text:)
let secondInit = Message.init(text:type:)

let firstMirror = Mirror(reflecting: firstInit)
let secondMirror = Mirror(reflecting: secondInit)

print(firstMirror.subjectType)
// (String) -> Message

print(secondMirror.subjectType)
// ((String, MessageType)) -> Message

然而,这段代码需要指定init,我想查找它。我期望的是以下内容:

let mirror = Mirror(reflecting: Message)

let inits = mirror.initializers
// something like [Message.init(text:), Message.init(text:type:)] as [Any]

for method in inits {
    let mirror = Mirror(reflecting: method)
    print(method.subjectType)
}

我怎样使用 Mirror 获取类中所有的 init 初始化器?

1个回答

5
在Swift中,Mirror结构体提供了一些运行时内省功能,但默认情况下,这些功能侧重于被反映实例本身,而不是该实例的类型。从语言参考中的Mirror可以看出:

Mirror

表示任意主题实例的子结构和可选“显示样式”。

概述

描述组成特定实例的部分,例如存储属性、集合元素、元组元素或活动枚举案例。还可以提供一个“显示样式”属性,建议如何呈现此结构。

通过符合CustomReflectable协议,您可以为您的Message类型实现自定义镜像。然而,仅为列出可用的初始化器实现自定义镜像仍需要手动提供初始化器的信息到自定义镜像的实现中。
例如:
extension Message: CustomReflectable {
    var customMirror: Mirror {
        let children = DictionaryLiteral<String, Any>(dictionaryLiteral:
            ("init(text:)", type(of: Message.init(text:))),
            ("init(text:type:)", type(of: Message.init(text:type:))))

        return Mirror.init(Message.self, children: children,
                           displayStyle: .class)
    }
}

// using your custom mirror
let myMessage = Message(text: "foo")
for case (let label?, let value) in Mirror(reflecting: myMessage).children {
    print("\(label), \(value)")
} /* init(text:), (String) -> Message
     init(text:type:), ((String, MessageType)) -> Message */

然而,手动实现此要求可能会打败练习的本意。请注意,仍然必须对实例进行反射,而不是类型本身(因此,直接将初始化程序作为一个static类型属性描述的字典可能更容易实现;但手动形式的这种实现则破坏了其大部分价值)。


那么在类级别上有更好的方法吗? - baryo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接