【问题标题】:How to get all class initializers using reflection in Swift如何在 Swift 中使用反射获取所有类初始值设定项
【发布时间】:2017-02-12 01:52:49
【问题描述】:

我正在尝试从 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 初始化程序?

【问题讨论】:

    标签: swift reflection initialization mirror


    【解决方案1】:

    Swift 中的 Mirror 结构提供了一些运行时自省功能,但在默认情况下,这些功能侧重于所反映的实例,而不是该实例的类型。来自language reference for 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 类型属性的字典可能更容易;但是这种实现的手动形式破坏了它的大部分价值)。

    【讨论】:

    • 那么有没有更好的方法在课堂上做到这一点?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    相关资源
    最近更新 更多