【问题标题】:What happens when you print a Swift object (po) in lldb?在 lldb 中打印 Swift 对象 (po) 时会发生什么?
【发布时间】:2014-11-21 14:20:49
【问题描述】:

Objective-C 中,当您在NSLog 一个对象或po 它在lldb 中时,该对象会收到description 消息。

然而,在 Swift 中,行为似乎有所不同。我实现了Printable(需要description 属性)和DebugPrintable(又需要一个名为debugDescription 的属性)。如果我尝试println() 一个对象或po 它,这些属性都不会被调用。

发生了什么事?那这些协议是干什么用的?

【问题讨论】:

    标签: objective-c cocoa swift lldb


    【解决方案1】:

    存在一个已知问题,即 Printable 被 Swift REPL 忽略(即 Playground 中的任何内容或在命令行由 xcrun swift 运行的任何内容)但被编译器识别(模拟器中的编译应用程序或 xcrun swiftc )。

    例如,这里是“foo.swift”的代码:

    struct Person : Printable {
        let name: String
    
        var description: String {
            return "\(name)"
        }
    }
    
    let me = Person(name: "Nate")
    println(me)
    

    如果我使用 REPL 运行它,我会得到:

    $ xcrun swift foo.swift 
    foo.Person
    

    但如果我先编译它,然后运行它,它会使用description 计算属性:

    $ xcrun -sdk macosx swiftc foo.swift ; ./foo
    Nate
    

    如果您希望能够使用debugPrintdebugPrintln 函数,DebugPrintable 协议很有用——在编译后的代码中,它们会打印出实例的debugDescription 属性。

    【讨论】:

    • 谁能想到...谢谢! ;-)
    • 顺便说一句,如果真的这样描述,有什么理由实现DebugPrintable吗?
    • @cfisher 我不知道! :)
    【解决方案2】:

    只是为 Nate 的回答添加更多细节:

    • 在 Xcode 6 中,当您尝试“po”一个 Swift 对象时,会发生以下两种情况之一:

      • 该对象实际上是一个 Objective-C 对象(例如 NSWindow、NSString),或者是此类类型的可选对象。在这种情况下,LLDB 会在必要时展开,然后调用 NSPrintForDebugger(objcpointer)。这意味着 ObjC 对象在 Swift 中的“po”应该与在 Objective-C 中一样

      • 该对象实际上是一个 Swift 对象。在这种情况下,LLDB 使用自己的数据格式化程序来打印对象,并进行一些小调整以提供“po”式外观,但无论您的对象实现什么协议,它们都会被忽略

    作为未来的增强,其想法是 LLDB 将能够向 Swift 标准库请求调试字符串(对象),并让 Swift 库处理操作的详细信息 - 很像 Objective- 中的 NSPrintForDebugger() C 世界。

    在这个增强的宇宙中,标准库的约定很可能是实现 Printable 或 DebugPrintable 会影响 toDebugString() 的结果。 LLDB 会自动流行起来,因为它只是在委派责任。

    即使在这样一个增强的宇宙中,由于 JIT 的限制,您在 REPL 模式下的里程也会有所不同。顺便说一句,同样的限制使您无法在 Playground 中定义类型并自定义其呈现方式(这需要实现至少一个 Reflectable/Mirror 协议)

    【讨论】:

    • 但是 Swift 中的 所有 对象都是 Objective-C 对象——所有对象都可以与 Objective-C 运行时一起使用(并非所有成员都对 Objective-C 可用;但对象本身与任何其他对象一样好)
    • 好吧,从这个意义上说,结构和枚举不是对象。但是,是的,让我更具体一点:前一种行为适用于 @class 类型的实例 imported from Objective-C
    • 其实no Swift 类是一个Objective-C 类。您可以通过创建 Objective-C 类的子类(例如 NSObject)或通过声明以 @objc 开头的类来使它们成为 Objective-C 类。
    【解决方案3】:

    试试:

    dump(object)
    

    了解更多here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-09
      • 2012-01-15
      • 2022-01-22
      • 2018-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多