Skip to content

Instantly share code, notes, and snippets.

@mhuusko5
Last active November 3, 2022 16:26
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save mhuusko5/81ecab40ebbea035abe8 to your computer and use it in GitHub Desktop.
Save mhuusko5/81ecab40ebbea035abe8 to your computer and use it in GitHub Desktop.
Swift – func deepDescription(any: Any) -> String (pretty print any object, recursively)
func deepDescription(any: Any) -> String {
guard let any = deepUnwrap(any) else {
return "nil"
}
if any is Void {
return "Void"
}
if let int = any as? Int {
return String(int)
} else if let double = any as? Double {
return String(double)
} else if let float = any as? Float {
return String(float)
} else if let bool = any as? Bool {
return String(bool)
} else if let string = any as? String {
return "\"\(string)\""
}
let indentedString: String -> String = {
$0.componentsSeparatedByCharactersInSet(.newlineCharacterSet()).map { $0.isEmpty ? "" : "\r \($0)" }.joinWithSeparator("")
}
let mirror = Mirror(reflecting: any)
let properties = Array(mirror.children)
guard let displayStyle = mirror.displayStyle else {
return String(any)
}
switch displayStyle {
case .Tuple:
if properties.count == 0 { return "()" }
var string = "("
for (index, property) in properties.enumerate() {
if property.label!.characters.first! == "." {
string += deepDescription(property.value)
} else {
string += "\(property.label!): \(deepDescription(property.value))"
}
string += (index < properties.count - 1 ? ", " : "")
}
return string + ")"
case .Collection, .Set:
if properties.count == 0 { return "[]" }
var string = "["
for (index, property) in properties.enumerate() {
string += indentedString(deepDescription(property.value) + (index < properties.count - 1 ? ",\r" : ""))
}
return string + "\r]"
case .Dictionary:
if properties.count == 0 { return "[:]" }
var string = "["
for (index, property) in properties.enumerate() {
let pair = Array(Mirror(reflecting: property.value).children)
string += indentedString("\(deepDescription(pair[0].value)): \(deepDescription(pair[1].value))" + (index < properties.count - 1 ? ",\r" : ""))
}
return string + "\r]"
case .Enum:
if let any = any as? CustomDebugStringConvertible {
return any.debugDescription
}
if properties.count == 0 { return "\(mirror.subjectType)." + String(any) }
var string = "\(mirror.subjectType).\(properties.first!.label!)"
let associatedValueString = deepDescription(properties.first!.value)
if associatedValueString.characters.first! == "(" {
string += associatedValueString
} else {
string += "(\(associatedValueString))"
}
return string
case .Struct, .Class:
if let any = any as? CustomDebugStringConvertible {
return any.debugDescription
}
if properties.count == 0 { return String(any) }
var string = "<\(mirror.subjectType)"
if displayStyle == .Class, let object = any as? AnyObject {
string += ": \(Unmanaged<AnyObject>.passUnretained(object).toOpaque())"
}
string += "> {"
for (index, property) in properties.enumerate() {
string += indentedString("\(property.label!): \(deepDescription(property.value))" + (index < properties.count - 1 ? ",\r" : ""))
}
return string + "\r}"
case .Optional: fatalError("deepUnwrap must have failed...")
}
}
func deepUnwrap(any: Any) -> Any? {
let mirror = Mirror(reflecting: any)
if mirror.displayStyle != .Optional {
return any
}
if let child = mirror.children.first where child.label == "Some" {
return deepUnwrap(child.value)
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment