I’m sure you’ve all seen the iOS Mail app, which displays the number of unread messages in a small red badge in the top right of the app icon. You can do this too with your Xojo app and the magic of the Declare command.
So how can this be used with Xojo? Using just five Declare commands, which I’ll cover step-by-step.
At first glance, it seems like it is as simple as using the property to set the badge number. Well, it used to be that simple in iOS 7 and earlier. But starting with iOS 8, you are now required to first get the user’s permission by calling the registerUserNotificationSettings method on UIApplication. Looking at that page, you’ll see that to register for a notification, you have to supply an instance of UIUserNotificationSettings that is configured for badge icon permission. So I’m going to start there.
But before jumping right in, there is a helper function I need in order to get references to iOS classes: NSClassFromString. So this is the first Declare and it looks like this:
Declare Function NSClassFromString Lib "Foundation" (name As CFStringRef) As Ptr
Now I can get a reference to UIUserNotificationSettings by calling this method:
Dim notificationSettings As Ptr = NSClassFromString("UIUserNotificationSettings")
This class has a shared method (settingsForTypes:categories:) that can be called to get an instance configured for use with registerUserNotificationSettings. Its Declare (our second) looks like this:
Declare Function settings Lib "UIKit" Selector "settingsForTypes:categories:" _ (obj As Ptr, allowedTypes As Integer, actionSettings As Ptr) As Ptr
Looking at that method declaration, note the trailing colon in the name. This is necessary because the method takes parameters. Do not forget to include it or the method will not be found and your app will crash when you run it.
The first parameter (obj As Ptr) is for you to pass in the reference to the UIUserNotificationSettings class. The second parameter (allowedTypes As Integer) is the type of notification you want to use, and the third parameter (actionSettings As Ptr) is for groups of notifications, but I won’t be using that.
You can now call the method by supplying the reference to the class we have stored in notificationSettings. For the allowedTypes, the value “1” indicates a badge icon notification:
Dim settingsObject As Ptr = settings(notificationSettings, 1, Nil)
This gives me an instance of UIUserNotificationSettings that I can then pass to the registerUserNotificationSettings method. In order to call that method I now need a reference to the UIApplication instance for the running app. To get that the third Declare is needed:
Declare Function sharedApplication Lib "UIKit" Selector "sharedApplication" (obj As Ptr) As Ptr
The Declare to call that method looks like this:
Dim sharedApp As Ptr = sharedApplication(NSClassFromString("UIApplication"))
This is the fourth declare to the registerUserNotificationSettings method:
Declare Sub registerUserNotificationSettings Lib "UIKit" Selector "registerUserNotificationSettings:" _ (obj As Ptr, settings As Ptr)
You call this method by passing in the reference to the shared app and the settings:
Lastly, we arrive at the fifth and final declare which calls the applicationIconBadgeNumber property that was the first thing I identified. Its Declare looks like this:
Declare Sub applicationIconBadgeNumber Lib "UIKit" Selector "setApplicationIconBadgeNumber:" _ (id As Ptr, value As Integer)
One thing to note is that because this is a property, the name has to be adjusted a bit. Rather than using “applicationIconBadgeNumber”, you have to use the name of the “setter”, which prefixes “set” and tweaks the casing. So the name instead is “setApplicationIconBadgeNumber:”. Remember the trailing colon since a parameter is passed!
And don’t forget that these Selector names are all case-sensitive!
And finally, you call the method like this to set the number 42 on the badge:
You’ll have to press home to get back to Springboard so you can see the app icon with the badge, of course!
You can download the project that adds this as an extension method to iOSApplication so you can call it like this:
And you are all set now!