gpt4 book ai didi

swift - 如何在 Swift 中使用反射获取所有类初始化器

转载 作者:可可西里 更新时间:2023-11-01 00:57:32 36 4
gpt4 key购买 nike

我正在尝试从 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 中的 Mirror 结构提供了一些运行时自省(introspection)功能,但对于默认情况,这些功能关注的是被反射的实例,而不是该实例的类型。来自language reference for Mirror :

Mirror

Representation of the sub-structure and optional “display style” of any arbitrary subject instance.

Overview

Describes the parts—such as stored properties, collection elements, tuple elements, or the active enumeration case—that make up a particular instance. May also supply a “display style” property that suggests how this structure might be rendered.

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

例如:

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 类型属性;但此实现的手动形式失去了它的大部分值(value))。

关于swift - 如何在 Swift 中使用反射获取所有类初始化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42183403/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com