2014-06-08 11 views
126

In Objective-C kann man eine description Methode zu ihrer Klasse hinzufügen:Was ist das Swift-Äquivalent von - [NSObject-Beschreibung]? bei der Fehlersuche zu unterstützen

@implementation MyClass 
- (NSString *)description 
{ 
    return [NSString stringWithFormat:@"<%@: %p, foo = %@>", [self class], foo _foo]; 
} 
@end 

dann in dem Debugger können Sie tun:

po fooClass 
<MyClass: 0x12938004, foo = "bar"> 

Was ist das Äquivalent in Swift ? Swifts REPL Ausgang kann hilfreich sein:

1> class MyClass { let foo = 42 } 
    2> 
    3> let x = MyClass() 
x: MyClass = { 
    foo = 42 
} 

Aber ich möchte dieses Verhalten außer Kraft zu setzen für den Druck auf die Konsole:

4> println("x = \(x)") 
x = C11lldb_expr_07MyClass (has 1 child) 

Gibt es eine Möglichkeit, diese println Ausgabe zu bereinigen? Ich habe das Printable Protokoll gesehen:

/// 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 } 
} 

ich dies automatisch durch println dachte würde „gesehen“, aber es scheint nicht der Fall zu sein:

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) 

Und stattdessen muss ich ausdrücklich nennen Beschreibung:

8> println("x = \(x.description)") 
x = MyClass, foo = 42 

Gibt es einen besseren Weg?

Antwort

76

Durch einige Experimente habe ich festgestellt, dass die Protokolle Printable und DebugPrintable beim Kompilieren einer tatsächlichen App funktionieren, aber nicht in der REPL oder Playground.

Side Hinweis: Der Code, den Sie richtig geschrieben ist, aber in diesem Fall suchen Sie wahrscheinlich für DebugPrintable


Swift diese Protokolle umbenannt CustomStringConvertible und CustomDebugStringConvertible zu sein - auch wenn der Compiler helfend zur Zeit Tells Sie es, dass :)

+3

Toller Fund! Ich werde eine Radar-Println-Ausgabe von "swift -i sample.swift" und "swift sample.swift && sample" eingeben. – Jason

+0

Danke für die Info dazu. Ich habe Printable auf einem Spielplatz ausprobiert und es funktioniert tatsächlich gerade nicht. Gut hört es sich in einer App an. –

+0

Printable funktioniert auf dem Spielplatz, aber wenn die Klasse von NSObject abstammt – dar512

50

getan Beispiel für die Verwendung CustomStringConvertible und CustomDebugStringConvertible Protokolle in 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) 
    } 

      ... 
} 

Welche ausdrucken:

**** PageContentViewController 
pageIndex equals 0 **** 

**** PageContentViewController 
pageIndex equals 0 **** 

---- PageContentViewController 
pageIndex equals 0 ---- 

Hinweis:, wenn Sie eine benutzerdefinierte Klasse haben, die nicht von jeder Klasse in UIKit Bibliotheken oder Foundation enthalten erbt, dann ist es von NSObject Klasse machen erben oder zu CustomStringConvertible und CustomDebugStringConvertible Protokollen machen entsprechen.

33

Verwenden Sie einfach CustomStringConvertible und var description: String { return "Some string" }

Werke in 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))" 
} 
7
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 
4
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 
19

Die Antworten auf CustomStringConvertible beziehen, sind der Weg zu gehen. Persönlich, um die Klasse (oder Struktur) Definition so sauber wie möglich zu halten, würde ich auch die Beschreibung Code in eine separate Erweiterung trennen:

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!" 
Verwandte Themen