I'm writing standalone Objective-C code to display notifications on MacOS. Here's what I have so far.
The main logic is in notify.m
:
#import <stdio.h>
#import <Cocoa/Cocoa.h>
#import <UserNotifications/UserNotifications.h>
#import <objc/runtime.h>
@interface AppDelegate : NSObject<NSUserNotificationCenterDelegate>
@end
@implementation AppDelegate
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
shouldPresentNotification:(NSUserNotification *)notification {
return YES;
}
@end
int native_show_notification(char *title, char *msg) {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *appdel = [[AppDelegate alloc] init];
app.delegate = appdel;
NSUserNotificationCenter *nc = [NSUserNotificationCenter defaultUserNotificationCenter];
nc.delegate = appdel;
NSUserNotification *n = [[NSUserNotification alloc] init];
n.title = [NSString stringWithUTF8String:title];
n.informativeText = [NSString stringWithUTF8String:msg];
[NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:n];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
return 0;
}
int main() {
const int a = 50, b = 150;
char title[a] = "Test\0", msg[b] = "Hello!\0";
native_show_notification(title, msg);
}
Along with the code, we have an Info.plist
in the same directory.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.microsoft.VSCode</string>
</dict>
</plist>
The compilation command is simple: cc -framework Cocoa -o app notif.m
. The Info.plist
is discovered and incorporated automatically.
This code works fine, with one caveat. If the application defined by the package name (in this case com.microsoft.VSCode
) is focused, the notification is not "pushed" to the user under default settings [1]. Instead it is hidden in the notification center. When the application in question is not focused, though, the notification is pushed properly. If you want to test this yourself, try compiling and running the code in VSCode, where it seems like nothing happened until you check your notification center. Then set the <string>
to something like com.apple.calendar
. It'll work.
How can I avoid this and get the notification to display no matter what?
[1] The default notification scheme is "Banner". The problem goes away when the user selects "Alert", but I cannot expect this. I'd like to get it working with Banner too.