如何在 Swift 中使用反射获取所有 class 初始化程序
How to get all class initializers using reflection in Swift
我正在尝试从 Swift 中的 class 获取初始化程序的所有签名。初始化器可以镜像,我可以找到如下代码的签名。
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 从 class 获取所有 init
初始化器?
Swift 中的 Mirror
结构提供了一些运行时内省功能,但对于默认情况,这些功能关注的是被反射的实例,而不是该实例的类型。来自 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
类型实现自定义镜像。然而,以列出可用初始化程序的单一目的实现自定义镜像,仍然需要手动将初始化程序的信息提供给自定义镜像的实现。
例如:
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
类型 属性 的字典;但是这个的手动形式实施破坏了它的大部分价值)。
我正在尝试从 Swift 中的 class 获取初始化程序的所有签名。初始化器可以镜像,我可以找到如下代码的签名。
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 从 class 获取所有 init
初始化器?
Swift 中的 Mirror
结构提供了一些运行时内省功能,但对于默认情况,这些功能关注的是被反射的实例,而不是该实例的类型。来自 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
类型实现自定义镜像。然而,以列出可用初始化程序的单一目的实现自定义镜像,仍然需要手动将初始化程序的信息提供给自定义镜像的实现。
例如:
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
类型 属性 的字典;但是这个的手动形式实施破坏了它的大部分价值)。