如何在 Swift 中使用反射获取所有类初始值设定项

Edw*_*ard 3 reflection initialization mirror swift

我试图从 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
Run Code Online (Sandbox Code Playgroud)

但是,此代码需要指定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)
}
Run Code Online (Sandbox Code Playgroud)

如何init使用 Mirror 从类中获取所有初始值设定项?

dfr*_*fri 5

Swift 中的结构Mirror体提供了一些运行时自省功能,但对于默认情况,这些功能侧重于所反射的实例而不是该实例的类型。从语言参考Mirror

\n\n
\n

镜子

\n\n

任意主题实例的子结构和可选 \xe2\x80\x9c 显示样式 \xe2\x80\x9d 的表示。

\n\n

概述

\n\n

描述构成特定实例的部分\xe2\x80\x94,例如存储属性、集合元素、元组元素或活动枚举情况\xe2\x80\x94。还可以提供 \xe2\x80\x9cdisplay style\xe2\x80\x9d 属性,该属性建议如何呈现此结构。

\n
\n\n

Message您可以通过遵守协议来为您的类型实现自定义镜像CustomReflectable。然而,实现具有列出可用初始化程序的单一目的的自定义镜像仍然需要手动向自定义镜像的实现提供初始化程序的信息。

\n\n

例如:

\n\n
extension Message: CustomReflectable {\n    var customMirror: Mirror {\n        let children = DictionaryLiteral<String, Any>(dictionaryLiteral:\n            ("init(text:)", type(of: Message.init(text:))),\n            ("init(text:type:)", type(of: Message.init(text:type:))))\n\n        return Mirror.init(Message.self, children: children,\n                           displayStyle: .class)\n    }\n}\n\n// using your custom mirror\nlet myMessage = Message(text: "foo")\nfor case (let label?, let value) in Mirror(reflecting: myMessage).children {\n    print("\\(label), \\(value)")\n} /* init(text:), (String) -> Message\n     init(text:type:), ((String, MessageType)) -> Message */\n
Run Code Online (Sandbox Code Playgroud)\n\n

不过,这种手动实施要求可能违背了练习的目的。另请注意,反射仍然必须在实例而不是类型本身上执行(因此,简单地实现直接将初始化程序描述为类型属性的字典可能更容易static;但是此实现的手动形式破坏了其大部分价值)。

\n