debugDescription property has been around for quite awhile. Formally first
appearing as a
@property on NSObject in iOS 5 and macOS
10.8, it came across into Swift as a member of the
CustomDebugStringConvertible protocol, and continues to be
incredibly useful today.
But somehow it still manages to surprise me when I find a detailed custom
implementation of the property, like the one I just discovered on
I don’t remember why I decided to try printing plain old
NSNotificationCenter.defaultCenter in lldb, but I do remember being very
surprised at the output. Rather than a plain object class-name-and-pointer pair
like most things return, I found a long list of registered notification
observers, complete with column headers:
(lldb) po NSNotificationCenter.defaultCenter <NSNotificationCenter:0x6140000da9b0> Name, Object, Observer, Options com.apple.accessibility.reduce.motion.status, 0x1055e61d0, 0x7f8df5300260, 1001 com.apple.accessibility.asst.scanner.status, 0x1055e61d0, 0x7f8df5300260, 1001 UIAccessibilitySingleSystemColorChangedNotification, 0x1055e61d0, 0x106d19998, 1400 com.apple.accessibility.button.shapes, 0x1055e61d0, 0x7f8df5300260, 1001 UIAccessibilityReduceMotionStatusDidChangeNotification, 0x1055e61d0, 0x60800005bc00, 1400 …
This was way more helpful than I had dared hope for: every observer, the
object it’s observing, and the name of the notification it’s waiting for. The
amount of introspection here gives KVO’s
observationInfo a run for its money.
The one downside is that I don’t have a great affinity for matching pointer addresses by sight, especially in the ocean of hexadecimal produced by sixty-plus lines of this output. What’s more, you’re practically guaranteed at least that much debugger spew, since the system frameworks register for quite a few notifications before your code even gets run.
I had to cut through the noise… and what better way to process an app’s debugging info than with another app?
A couple hours later, NotificationDebugger was born: a Mac app that takes a
table of pointers and corresponding names, plus a text dump of
debugDescription, and produces a table of only the
observations involving a named pointer.
It’s definitely got my coder’s design sensibilities (i.e. no labels on anything, anywhere) – but it solved the problem I was facing, which is good enough for publication on GitHub. Find the source here, and let me know if this is useful to you!