En Objective-C, on peut append une méthode de description
à leur classe pour faciliter le débogage:
@implementation MyClass - (NSSsortingng *)description { return [NSSsortingng ssortingngWithFormat:@"", [self class], foo _foo]; } @end
Ensuite, dans le débogueur, vous pouvez faire:
po fooClass
Quel est l’équivalent dans Swift? La sortie REPL de Swift peut être utile:
1> class MyClass { let foo = 42 } 2> 3> let x = MyClass() x: MyClass = { foo = 42 }
Mais j’aimerais remplacer ce comportement pour imprimer sur la console:
4> println("x = \(x)") x = C11lldb_expr_07MyClass (has 1 child)
Y a-t-il un moyen de nettoyer cette sortie d’ println
? J’ai vu le protocole 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: Ssortingng { get } }
J’ai pensé que cela serait automatiquement “vu” par println
mais cela ne semble pas être le cas:
1> class MyClass: Printable { 2. let foo = 42 3. var description: Ssortingng { 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)
Et au lieu de cela, je dois explicitement appeler la description:
8> println("x = \(x.description)") x = MyClass, foo = 42
Y a-t-il une meilleure façon?
Pour l’implémenter sur un type Swift, vous devez implémenter le protocole CustomSsortingngConvertible
, puis implémenter également une propriété de chaîne appelée description
.
Par exemple:
class MyClass: CustomSsortingngConvertible { let foo = 42 var description: Ssortingng { return "<\(type(of: self)): foo = \(foo)>" } } print(MyClass()) // prints:
Remarque: type(of: self)
obtient le type des instances en cours au lieu d’écrire explicitement “MyClass”.
Exemple d’utilisation des protocoles CustomSsortingngConvertible
et CustomDebugSsortingngConvertible
dans Swift:
PageContentViewController.swift
import UIKit class PageContentViewController: UIViewController { var pageIndex : Int = 0 override var description : Ssortingng { return "**** PageContentViewController\npageIndex equals \(pageIndex) ****\n" } override var debugDescription : Ssortingng { 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) } ... }
Qui imprime:
**** PageContentViewController pageIndex equals 0 **** **** PageContentViewController pageIndex equals 0 **** ---- PageContentViewController pageIndex equals 0 ----
Remarque: si vous avez une classe personnalisée qui n’hérite d’aucune classe incluse dans les bibliothèques UIKit ou Foundation , faites-la hériter de la classe NSObject
ou rendez-la conforme aux protocoles CustomSsortingngConvertible
et CustomDebugSsortingngConvertible
.
Utilisez simplement CustomSsortingngConvertible
et var description: Ssortingng { return "Some ssortingng" }
fonctionne dans Xcode 7.0 bêta
class MyClass: CustomSsortingngConvertible { var ssortingng: Ssortingng? var description: Ssortingng { //return "MyClass \(ssortingng)" return "\(self.dynamicType)" } } var myClass = MyClass() // this line outputs MyClass nil // and of course print("\(myClass)") // Use this newer versions of Xcode var description: Ssortingng { //return "MyClass \(ssortingng)" return "\(type(of: self))" }
Les réponses relatives à CustomSsortingngConvertible
sont la voie à suivre. Personnellement, pour que la définition de classe (ou de structure) rest aussi claire que possible, je séparerais également le code de description en une extension distincte:
class foo { // Just the basic foo class stuff. var bar = "Humbug!" } extension foo: CustomSsortingngConvertible { var description: Ssortingng { return bar } } let xmas = foo() print(xmas) // Prints "Humbug!"
class SomeBaseClass: CustomSsortingngConvertible { //private var ssortingng: Ssortingng = "SomeBaseClass" var description: Ssortingng { return "\(self.dynamicType)" } // Use this in newer versions of Xcode var description: Ssortingng { 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: CustomSsortingngConvertible { let yearStart: Int let yearStop: Int var description: Ssortingng { return "\(yearStart)-\(yearStop)" } } let wp = WorldPeace(yearStart: 2020, yearStop: 2040) print("world peace: \(wp)") // outputs: // world peace: 2020-2040
Comme décrit ici , vous pouvez également utiliser les capacités de reflection de Swift pour que vos classes génèrent leur propre description en utilisant cette extension:
extension CustomSsortingngConvertible { var description : Ssortingng { var description: Ssortingng = "\(type(of: self)){ " let selfMirror = Mirror(reflecting: self) for child in selfMirror.children { if let propertyName = child.label { description += "\(propertyName): \(child.value), " } } description = Ssortingng(description.dropLast(2)) description += " }" return description } }