Friday, October 4, 2019

NSDistributedNotificationCenter No Longer Supports nil Names

merlinme (via Jeff Johnson):

I’m not sure if this is a bug or an API change, but we have an app which relies on distributed notifications which didn’t work on Catalina. After debugging I think the problem is that specifying a name: nil in addObserver fails silently.


Apple have now replied to my Feedback submission to confirm that the API has changed. Specifying a nil name in addObserver is now a privileged operation, so for practical purposes all applications currently using a nil name will stop receiving notifications when they move to Catalina, and will need to be updated to use a specified name.

Another breaking change to an API that’s been around since Mac OS X 10.10, without updating the documentation or mentioning the change in a release note:

notificationName The name of the notification for which to register the observer; that is, only notifications with this name are delivered to the observer. When nil, the notification center doesn’t use a notification’s name to decide whether to deliver it to the observer.

I guess maybe there are privacy reasons to prevent an app from seeing notifications from other apps or the system. However:

8 Comments RSS · Twitter

"It does make things more difficult for legitimate apps that are trying to improve the user experience by monitoring and responding to system changes."

You can't do anything useful without knowing the name of the notification you receive anyway. The major drawback is that know it make it harder to discover them.

That said, if an app running as `root` user can still get them, it would still be possible for devs to discover the notifications and update their apps accordingly.

@Jean-Daniel Yes, that’s what I mean: harder to discover them. Do we know that nil works when running as root?

It's important to note that the primary use of nil for the notification name parameter is not for "discovery". The primary use is for observing multiple notifications from the same sender. This can occur even when the sender and receiver are both your own processes. The API is almost exactly the same as NSNotificationCenter, where you might also use nil to observe multiple notifications from the same sender. This is why the undocumented NSDistributedNotificationCenter change is so bad. If it's for "security", it's merely security theater and breaks legitimate uses of the API.

@Jeff Right, there are two issues here: (1) discovery, no easy workaround, (2) observing multiple of your own notifications, breaks perfectly good code, but easy to work around.

I should have tested before I commented. The Apple Developer forums post didn't have any code, and It turns out that the situation is more complex than "merlinme" suggests:

Alexander Momchilov

Is this totally inoperative? I tried even running my program as root, and still don't receive any notifications.

If it's an intended change for privacy or security reasons, you'd think they'd have found time in the past two and a half years to document it.

As an experiment, in maOS Sonoma (v14.3.1) I removed the hardened runtime and app sandboxing entitlements and ran a test app from the command line with

% sudo

In that app, I'd called:

NSDistributedNotificationCenter *nc = NSDistributedNotificationCenter.defaultCenter;
[nc addObserver:self selector:@selector(didReceive:) name:nil object:nil];

where didReceive: just NSLog()s the notification. When I switched the Mac between light mode and dark mode, I did receive a pair of notifications with the names ApplePrivateInterfaceThemeChangedNotification and AppleInterfaceThemeChangedNotification

so, it sort of works.

But the question I'm really interest in is how some Apple apps are able to respond to System Settings > Accessibility > Display > Text > Text Size > Custom - I'd like to opt in to this in my own apps, but Apple doesn't say how.

Leave a Comment