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
I know it’s very likely that they’re aware but bound to NSLog for a reason I’m not privy to, but just in case they’re not aware of the `print()` and `debugPrint()` functions it’s worth mentioning that they’re the Swift-native method of doing what you’d normally use NSLog for.
`debugPrint()` in particular was something I wasn’t across until I RTFM recently, very nice in many use cases over `print()`.
Be careful with `NSLog` – it treats its first argument as a format string. So if you’re printing something with lots of `%`’s in it – like, say, a URL with an encoded query string – you can crash. c.f. https://github.com/fpillet/NSLogger/issues/19.