스위프트는-[NSObject description]에 해당하는 것은 무엇입니까?


163

Objective-C description에서 디버깅에 도움을주기 위해 클래스에 메소드를 추가 할 수 있습니다 .

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

그런 다음 디버거에서 다음을 수행 할 수 있습니다.

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

Swift와 동등한 기능은 무엇입니까? Swift의 REPL 출력이 도움이 될 수 있습니다.

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

그러나 콘솔에 인쇄하기 위해이 동작을 무시하고 싶습니다.

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

println출력 을 정리하는 방법이 있습니까? 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 }
}

나는 이것이 자동으로 "보일"것이라고 생각 println했지만 그것은 사실이 아닙니다.

  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)

대신 명시 적으로 설명을 호출해야합니다.

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

더 좋은 방법이 있습니까?

답변:


124

Swift 유형에서이를 구현하려면 CustomStringConvertible프로토콜을 구현 한 다음이라는 문자열 속성도 구현 해야합니다 description.

예를 들면 다음과 같습니다.

class MyClass: CustomStringConvertible {
    let foo = 42

    var description: String {
        return "<\(type(of: self)): foo = \(foo)>"
    }
}

print(MyClass()) // prints: <MyClass: foo = 42>

참고 : type(of: self)'MyClass'를 명시 적으로 작성하는 대신 현재 인스턴스 유형을 가져옵니다.


3
좋은 발견! "swift -i sample.swift"와 "swift sample.swift && sample"의 println 출력이 다른 레이더를 제출하려고합니다.
Jason

정보를 주셔서 감사합니다. 놀이터에서 Printable을 시험해 보았는데 실제로 작동하지 않습니다. 앱에서 작동한다고 들었습니다.
Tod Cunningham

Printable은 놀이터에서 작동하지만 수업이 NSObject에서 내려 오는 경우
dar512

5
스위프트 2.0은 CustomStringConvertible 및 CustomDebugStringConvertible 변경되었습니다
마이크 Vosseller

또한 Xcode 7.2가있는 놀이터에서 CustomStringConvertible 및 CustomDebugStringConvertible을 사용하는 데는 문제가 없습니다.
Nicholas Credli

54

Swift에서 사용 CustomStringConvertibleCustomDebugStringConvertible프로토콜의 예 :

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

          ...
}

인쇄물 :

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

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

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

참고 : UIKit 또는 Foundation 라이브러리에 포함 된 클래스에서 상속되지 않은 사용자 정의 클래스가있는 경우 클래스를 상속 NSObject하거나 프로토콜 CustomStringConvertibleCustomDebugStringConvertible프로토콜을 따르십시오 .


이 함수는 public으로 선언되어야합니다
Karsten

35

그냥 사용 CustomStringConvertible하고var description: String { return "Some string" }

Xcode 7.0 베타에서 작동

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))"
}

20

관련된 답변 CustomStringConvertible은 갈 길입니다. 개인적으로 클래스 (또는 구조체) 정의를 가능한 한 깨끗하게 유지하려면 설명 코드를 별도의 확장으로 분리합니다.

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

8
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

6

여기 에 설명 된대로 Swift의 리플렉션 기능을 사용하여이 확장을 사용하여 클래스가 자체 설명을 생성하도록 할 수도 있습니다.

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

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.