'Listing all class attributes swift 3
I'm trying to print all the values from an object that inherits from a class, here is my example:
I create the class:
class Pokemon {
var name: String?
var type: String?
var level: Int?
var exp = 0.0
}
Create the object and assign some values:
var pikachu = Pokemon()
pikachu.name = "Pika Pika"
pikachu.level = 1
pikachu.type = "electricity"
pikachu.exp = 0
Now I would like to loop through all the pikachu object attributes and print the values. I'm thinking in a for each loop but I'm not sure how to implement it.
I know I can do something like this:
func printStats(pokemon: Pokemon) {
if pokemon.name != nil {
print(" name: \(pokemon.name!)\n level:\(pokemon.level!)\n type:\(pokemon.type!)\n exp: \(pokemon.exp!)")
}
}
printStats(pokemon: pikachu)
output:
name: Pika Pika
level:1
type:electricity
exp: 0.0
But I just want to loop through all values, instead of explicit writing every attribute in the function.
Solution 1:[1]
I found it the way of doing it:
let pokeMirror = Mirror(reflecting: pikachu)
let properties = pokeMirror.children
for property in properties {
print("\(property.label!) = \(property.value)")
}
output:
name = Optional("Pika Pika")
type = Optional("electricity")
level = Optional(1)
exp = Optional(0.0)
and if you want to remove the "Optional" just initialize the attributes.
Solution 2:[2]
Looks like a duplicate of Does Swift support reflection?
Alternatively, you can use a dictionary to store the attributes of Any?
type.
e.g.
class Pokemon {
var attributes = [String:Any?]()
}
var pikachu = Pokemon()
pikachu.attributes["name"] = "Pika Pika"
pikachu.attributes["level"] = 1
pikachu.attributes["type"] = "electricity"
pikachu.attributes["exp"] = 0
func printStats(pokemon: Pokemon) {
pokemon.attributes.forEach { key, value in
if let value = value {
print("\(key): \(value)")
}
}
}
Solution 3:[3]
-
- use
Mirror API
to get instance's properties
- use
-
- if you are developing iOS app, using NSObject, you may want to override description. Then can use
print
to print the instance.
- if you are developing iOS app, using NSObject, you may want to override description. Then can use
A mirror describes the parts that make up a particular instance, such as the instance’s stored properties, collection or tuple elements, or its active enumeration case.
class YourClass: NSObject {
public override var description: String {
var des: String = "\(type(of: self)) :"
for child in Mirror(reflecting: self).children {
if let propName = child.label {
des += "\(propName): \(child.value) \n"
}
}
return des
}
}
let instance = YourClass()
print(instance)
see more in Reflection in Swift
Solution 4:[4]
In Swift 5 you can create a new func
in your class:
func debugLog() {
print(Mirror(reflecting: self).children.compactMap { "\($0.label ?? "Unknown Label"): \($0.value)" }.joined(separator: "\n"))
}
And then call it with MyObject().debugLog()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | extrablade |
Solution 2 | Community |
Solution 3 | RY_ Zheng |
Solution 4 | Radu Ursache |