Dear Erica: Why doesn’t NSLog support Swift objects

Dear Erica, when I try to run the following code in a playground, Xcode dies, with the complaint “error: ‘NSLog’ is unavailable: Variadic function is unavailable NSLog(“%@”, Foo()) Foundation.NSLog:2:13: note: ‘NSLog’ has been explicitly marked unavailable here“. What gives?

import Foundation
class Foo {}
NSLog("%@", Foo())

Your first problem is that Foo is not an NSObject.  If you subclass Foo from NSObject, the error goes away and the log statement outputs “<__lldb_expr_24.Foo: 0x7fc9d2920210>“. Still not exactly what you’re looking for, I know.

The reason is that in our discussion going back and forth I know you wanted to use CustomDebugStringConvertible with NSLog and the way you make that happen is by using normal string interpolation with NSLog:

class Foo: CustomDebugStringConvertible {
    var debugDescription: String {return "Superfoo!"}
}

NSLog("\(Foo())")

Swift and NSLog aren’t really set up to do the format string interoperation you were looking for. However, if you’re bound and determined to do so, there is a solution:

class Bar: NSObject {
    override var description: String {return "Superbar!"}
}

NSLog("%@", Bar())

In this case, instead of trying to conform to CustomDebugStringConvertible, you override the built-in NSObject property to get the custom output you were looking for. Implementing description (OS X 10.10 and later) returns a string that “describes the contents of the receiver”. NSLog can then use this result to create a textual representation of your object, which can be used in a formatted string.

2016-05-02 14:12:43.106 Untitled Page 3[5161:524832] Superfoo!
2016-05-02 14:12:43.107 Untitled Page 3[5161:524832] Superbar!

Like in Swift native classes, NSObject also supports a debug variation (debugDescription, OS X 10.8 and later), which is preferred for presentation in the debugger.

3 Comments