Reputation: 3948
Given this Model:
public class RSS2Feed {
public var channel: RSS2FeedChannel?
public init() {}
}
public class RSS2FeedChannel {
public var title: String?
public var description: String?
public init() {}
}
What would I need to do in order to get the property names and values of an RSS2FeedChannel
instance?
Here's what I'm trying:
let feed = RSS2Feed()
feed.channel = RSS2FeedChannel()
feed.channel?.title = "The Channel Title"
let mirror = Mirror(reflecting: feed.channel)
mirror.children.first // ({Some "Some"}, {{Some "The Channel Title...
for (index, value) in mirror.children.enumerate() {
index // 0
value.label // "Some"
value.value // RSS2FeedChannel
}
Ultimately, I'm trying to create a Dictionary
that matches the instance, using reflection, but so far I'm unable to get the properties name and values of the instance.
Documentation says that:
The optional label may be used when appropriate, e.g. to represent the name of a stored property or of an active enum case, and will be used for lookup when Strings are passed to the descendant method.
Yet I only get a "Some" string.
Also, the value property is returning a string with the Type RSS2FeedChannel
when I would expect each children to be "An element of the reflected instance's structure."!
Upvotes: 5
Views: 4629
Reputation: 2073
When i understand correct this should solve ur problem:
func aMethod() -> Void {
let feed = RSS2Feed()
feed.channel = RSS2FeedChannel()
feed.channel?.title = "The Channel Title"
// feed.channel?.description = "the description of your channel"
guard let channel = feed.channel else {
return
}
let mirror = Mirror(reflecting: channel)
for child in mirror.children {
guard let key = child.label else {
continue
}
let value = child.value
guard let result = self.unwrap(value) else {
continue
}
print("\(key): \(result)")
}
}
private func unwrap(subject: Any) -> Any? {
var value: Any?
let mirrored = Mirror(reflecting:subject)
if mirrored.displayStyle != .Optional {
value = subject
} else if let firstChild = mirrored.children.first {
value = firstChild.value
}
return value
}
just some little changes for swift 3:
private func unwrap(_ subject: Any) -> Any? {
var value: Any?
let mirrored = Mirror(reflecting:subject)
if mirrored.displayStyle != .optional {
value = subject
} else if let firstChild = mirrored.children.first {
value = firstChild.value
}
return value
}
Upvotes: 5
Reputation: 11341
You can use the descendent
method on the Mirror object to get this information. It will return nil if the values aren't found or the optionals contain no value.
let mirror = Mirror(reflecting: feed.channel)
let child1 = mirror.descendant("Some", "title") // "The Channel Title"
// or on one line
let child3 = Mirror(reflecting: feed).descendant("channel", "Some", "title")
Upvotes: 1