Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A default protocol implementation for CustomDebugStringConvertible that uses Mirror for introspection
public extension CustomDebugStringConvertible {
var debugDescription: String {
return debugDescription()
}
func debugDescription(_ indentationLevel: Int = 0, includeType: Bool = true) -> String {
let indentString = (0..<indentationLevel).reduce("") { tabs, _ in tabs + "\t" }
var s: String
if includeType {
s = "\(type(of: self))"
} else {
s = ""
}
let mirror = Mirror(reflecting: self)
let children = mirror.children
if children.count == 0 {
return s + " = \(debugDescription),"
}
if s.hasPrefix("Optional<") {
let child = children.first!
if let aChild = child.1 as? CustomDebugStringConvertible {
s += aChild.debugDescription(indentationLevel, includeType: false)
} else {
s += "\(child.1),"
}
s += "\(indentString)"
} else if let date = self as? Date {
s += " = \(date),"
} else {
s += " {"
var index = 0
s = children.reduce(s) { reducedString, child in
var propertyName: String = ""
if self is Array<Any> {
propertyName = String(index)
index += 1
} else {
propertyName = child.label ?? "<undefined>"
}
if let aChild = child.value as? CustomDebugStringConvertible {
let childDescription = aChild.debugDescription(indentationLevel + 1)
return reducedString + "\n\(indentString)\t\(propertyName): \(childDescription)"
} else {
return reducedString + "\n\(indentString)\t\(propertyName): \(type(of: child.value)) = \(child.value),"
}
}
s = s.substring(to: s.characters.index(before: s.characters.endIndex))
s += "\n\(indentString)}"
}
return s
}
}
/*
// Sample usage
struct Person: CustomDebugStringConvertible {
let name: String
let address: Address
let children: [Person]?
}
struct Address: CustomDebugStringConvertible {
let city: String
let state: String
let zip: String
let streetNumber: String
let streetName: String
let suiteNumber: String?
let randomNumber: Int
init(city: String, state: String, zip: String, streetNumber: String, streetName: String, suiteNumber: String? = nil) {
self.city = city
self.state = state
self.zip = zip
self.streetNumber = streetNumber
self.streetName = streetName
self.suiteNumber = suiteNumber
self.randomNumber = Int(arc4random_uniform(1000))
}
}
let address = Address(city: "Lehi", state: "UT", zip: "84043", streetNumber: "123", streetName: "Fake st")
print(address)
let child = Person(name: "joe", address: address, children: nil)
let person = Person(name: "matt", address: address, children: [child])
print(person)
*/
@thomasneuteboom

This comment has been minimized.

Copy link

commented Dec 8, 2015

+1. Thanks for this. Would be cool if it would also provide it's super class variables as an optional parameter in the function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.