NightFuryLxD
NightFuryLxD

Reputation: 845

Using custom NotificationCenter

I have an iOS app consisting of few libs and an app target. An iOS app can be launched in many ways like tapping a file, deep link, universal link, launched from a QuickAction etc. The information about how it's launched is passed to the SceneDelegate's scene(_:willConnectTo:options:). Now, I want to broadcast this information to all libraries, who would have registered observers earlier.

I'm thinking of using NotificationCenter, but there's this following line in Apple documentation when obtaining the default instance.

If your app uses notifications extensively, you may want to create and post to your own notification centers rather than posting only to the default notification center. When a notification is posted to a notification center, the notification center scans through the list of registered observers, which may slow down your app. By organizing notifications functionally around one or more notification centers, less work is done each time a notification is posted, which can improve performance throughout your app.

So, instead of using the default NotificationCenter from which we get lifecycle events like didBecomeActiveNotification, I was looking to create a custom NotificationCenter. But I couldn't find any examples on how to do this, even in apple documentation.... where there was a mention of using custom NotificationCenter (as quoted above), but that's it.

I tested out the following code. Custom notification is created by instantiating the NotificationCenter, as shown below:

// Creating a custom notification centre
public static let notificationCenter: NotificationCenter = NotificationCenter()

When registering for the notification:

sQuickActionLaunchNotificationObserver = notificationCenter.addObserver(forName: Notification.Name("QUICK_ACTION_LAUNCH"), object: nil, queue: nil, using: handleNotificationBroadcasts)

func handleNotificationBroadcasts(_ broadcastNotification: Notification) {         
    // Handle the notification 
}

Now, when the app gets launched by a shortcut, I broadcast a notification as follows:

// Somewhere in the SceneDelegate's scene(_:willConnectTo:options:), when app is launched using QuickAction (shortcut)
notificationCenter.post(name: Notification.Name("QUICK_ACTION_LAUNCH"), object: nil, userInfo["QuickActionKey":shortcutItem])

I'm creating a custom notification centre (not using the default), using it for registrations and also using it to post notification... and all of this works.

But is the above approach correct? I'm confused because I couldn't get any info on using custom NotificationCenter to broadcast in the Apple documentation. There are some examples online, but in those examples, people have subclassed and added some functionality. But I don't need any additional functionality... I'm only creating a new instance because it was recommended to create a custom NotificationCenter to avoid the performance impact due to too many observers. I only want to validate this approach.

Then, the reason for using a custom notification centre is to avoid a performance impact due to adding too many observers. This much is mentioned in the documentation (also quoted above), but how much is too many? I will probably have 20-30 notifications (very approximate) registered and in the handler which gets invoked with the Notification object, I'm thinking of moving the code execution to a background thread first, return the UI thread and continue my processing in the background thread..... since UI thread has to returned asap. So, basically, registering how many observers can cause this performance impact?

Upvotes: 0

Views: 323

Answers (1)

Rob Napier
Rob Napier

Reputation: 299565

I'm only creating a new instance because it was recommended to create a custom NotificationCenter to avoid the performance impact due to too many observers. I only want to validate this approach. ... I will probably have 20-30 notifications (very approximate) registered

By "registered," I assume you mean observers rather than notifications. This is a very, very small number of observers. Use the default NotificationCenter.

I don't recommend custom centers, and Apple isn't really either. Before ObjC added blocks (similar to Swift closures), a lot more work was done with notifications, on a lot less powerful hardware than a modern iPhone. NSNotificationCenter goes all the way back to NeXTSTEP. Scanning a large observer list in an app that used notifications "extensively" could become a problem. But this would be extremely unusual in a modern Swift app on iOS.

In almost 20 years of Cocoa development, I have only once ever overworked the NSNotificationCenter. I experimented once, years ago (long before Swift), with doing all callbacks with NSNotifications. Ultimately, we had around 5000 observers, posting several notifications a second. That made scrolling a bit slow.

You'd never build something that way today (and it wasn't a good idea at the time). You don't need a separate NotificationCenter, and in my experience, having a separate one tends to be error-prone. Eventually you wind up posting to the wrong one, and the symptom is "nothing happens" which is hard to debug.

Upvotes: 2

Related Questions