the - swift wikipedia
¿Cuál es el equivalente de Swift de-[descripción de NSObject]? (7)
En Objective-C, uno puede agregar un método de description
a su clase para ayudar en la depuración:
@implementation MyClass
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p, foo = %@>", [self class], foo _foo];
}
@end
Luego, en el depurador, puede hacer:
po fooClass
<MyClass: 0x12938004, foo = "bar">
¿Cuál es el equivalente en Swift? La salida REPL de Swift puede ser útil:
1> class MyClass { let foo = 42 }
2>
3> let x = MyClass()
x: MyClass = {
foo = 42
}
Pero me gustaría sobrescribir este comportamiento para imprimir en la consola:
4> println("x = /(x)")
x = C11lldb_expr_07MyClass (has 1 child)
¿Hay alguna manera de limpiar este println
impresión? He visto el protocolo Printable
:
/// This protocol should be adopted by types that wish to customize their
/// textual representation. This textual representation is used when objects
/// are written to an `OutputStream`.
protocol Printable {
var description: String { get }
}
Pensé que esto sería "visto" println
por println
pero no parece ser el caso:
1> class MyClass: Printable {
2. let foo = 42
3. var description: String { get { return "MyClass, foo = /(foo)" } }
4. }
5>
6> let x = MyClass()
x: MyClass = {
foo = 42
}
7> println("x = /(x)")
x = C11lldb_expr_07MyClass (has 1 child)
Y en su lugar tengo que llamar explícitamente la descripción:
8> println("x = /(x.description)")
x = MyClass, foo = 42
¿Hay una mejor manera?
Como se describe here , también puede usar las capacidades de reflexión de Swift para hacer que sus clases generen su propia descripción usando esta extensión:
extension CustomStringConvertible {
var description : String {
var description: String = "/(type(of: self)){ "
let selfMirror = Mirror(reflecting: self)
for child in selfMirror.children {
if let propertyName = child.label {
description += "/(propertyName): /(child.value), "
}
}
description = String(description.dropLast(2))
description += " }"
return description
}
}
Las respuestas relacionadas con CustomStringConvertible
son el camino a seguir. Personalmente, para mantener la definición de clase (o estructura) lo más limpia posible, también separaría el código de descripción en una extensión separada:
class foo {
// Just the basic foo class stuff.
var bar = "Humbug!"
}
extension foo: CustomStringConvertible {
var description: String {
return bar
}
}
let xmas = foo()
print(xmas) // Prints "Humbug!"
Para implementar esto en un tipo Swift, debe implementar el protocolo CustomStringConvertible
y luego implementar una propiedad de cadena llamada description
.
Por ejemplo:
class MyClass: CustomStringConvertible {
let foo = 42
var description: String {
return "</(type(of: self)): foo = /(foo)>"
}
}
print(MyClass()) // prints: <MyClass: foo = 42>
Nota: type(of: self)
obtiene el tipo de las instancias actuales en lugar de escribir explícitamente ''MyClass''.
Simplemente use CustomStringConvertible
y var description: String { return "Some string" }
funciona en Xcode 7.0 beta
class MyClass: CustomStringConvertible {
var string: String?
var description: String {
//return "MyClass /(string)"
return "/(self.dynamicType)"
}
}
var myClass = MyClass() // this line outputs MyClass nil
// and of course
print("/(myClass)")
// Use this newer versions of Xcode
var description: String {
//return "MyClass /(string)"
return "/(type(of: self))"
}
Ejemplo de uso de protocolos CustomStringConvertible
y CustomDebugStringConvertible
en Swift:
PageContentViewController.swift
import UIKit
class PageContentViewController: UIViewController {
var pageIndex : Int = 0
override var description : String {
return "**** PageContentViewController/npageIndex equals /(pageIndex) ****/n"
}
override var debugDescription : String {
return "---- PageContentViewController/npageIndex equals /(pageIndex) ----/n"
}
...
}
ViewController.swift
import UIKit
class ViewController: UIViewController
{
/*
Called after the controller''s view is loaded into memory.
*/
override func viewDidLoad() {
super.viewDidLoad()
let myPageContentViewController = self.storyboard!.instantiateViewControllerWithIdentifier("A") as! PageContentViewController
print(myPageContentViewController)
print(myPageContentViewController.description)
print(myPageContentViewController.debugDescription)
}
...
}
Que imprimir:
**** PageContentViewController
pageIndex equals 0 ****
**** PageContentViewController
pageIndex equals 0 ****
---- PageContentViewController
pageIndex equals 0 ----
Nota: si tiene una clase personalizada que no hereda de ninguna clase incluida en las bibliotecas UIKit o Foundation , NSObject
heredar de la clase NSObject
o haga que se ajuste a los protocolos CustomStringConvertible
y CustomDebugStringConvertible
.
class SomeBaseClass: CustomStringConvertible {
//private var string: String = "SomeBaseClass"
var description: String {
return "/(self.dynamicType)"
}
// Use this in newer versions of Xcode
var description: String {
return "/(type(of: self))"
}
}
class SomeSubClass: SomeBaseClass {
// If needed one can override description here
}
var mySomeBaseClass = SomeBaseClass()
// Outputs SomeBaseClass
var mySomeSubClass = SomeSubClass()
// Outputs SomeSubClass
var myOtherBaseClass = SomeSubClass()
// Outputs SomeSubClass
struct WorldPeace: CustomStringConvertible {
let yearStart: Int
let yearStop: Int
var description: String {
return "/(yearStart)-/(yearStop)"
}
}
let wp = WorldPeace(yearStart: 2020, yearStop: 2040)
print("world peace: /(wp)")
// outputs:
// world peace: 2020-2040