Unable to show simple notification on macOS - swift

Im Sort of new to Swift. I trying to create a console app/utility that creates a notification pop-up on macOS. I cant seem to find any way of doing this without. Its seems like this should be simple but im unable to get the notification pop-up to show :(
Im using swift 4.0.3 on macOS Sierra
Any guidance to get this work at the most basic level would be greatly appreciated! thanks!
import Foundation
import Cocoa
let notification = NSUserNotification()
notification.title = "Title of notification"
notification.subtitle = "Subtitle of notification"
notification.soundName = NSUserNotificationDefaultSoundName
NSUserNotificationCenter.default.deliver(notification)

Your notification is only delivered when your app is not focused.
If you want to deliver it anyway, you need to implement NSUserNotificationCenterDelegate as a protocol and these functions:
func userNotificationCenter(_ center: NSUserNotificationCenter, shouldPresent notification: NSUserNotification) -> Bool { return true }
private func userNotificationCenter(_ center: NSUserNotificationCenter, didActivate notification: NSUserNotification) -> Bool { return true }
public func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool { return true }
PS. I'm pretty sure, that not all of them are needed - but I don't know which ones are

Related

Notification does not trigger userNotificationCenter on macOS Big Sur 11.6

When I run app using terminate argument (set using “Product“ / “Scheme” / “Edit Scheme…” / “Run” / “Arguments” / “Argument Passes On Launch”), a notification appears in macOS Notification Centre and app terminates.
#testapp application did finish launching
#testapp terminate mode enabled
#testapp terminating…
So far, so good… Expected.
When I click notification, app launches but userNotificationCenter is not triggered (I don’t see #testapp notification triggered in Console app, but I see following).
#testapp application did finish launching
#testapp terminating…
Not normal right? How can I fix this?
I am starting to think that this is a Big Sur bug in version 11.6.
Everything works fine on Big Sur version 11.4 (M1) and 11.5 (Intel).
Thanks for helping out!
//
// AppDelegate.swift
// Test
//
// Created by Sun Knudsen on 2021-10-22.
//
import Cocoa
import UserNotifications
#main
class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate {
func showNotification(){
let content = UNMutableNotificationContent()
content.body = "Hello"
let request = UNNotificationRequest(
identifier: UUID().uuidString,
content: content,
trigger: nil
)
UNUserNotificationCenter.current().add(request)
}
func terminate() -> Void {
DispatchQueue.main.async {
NSApp.terminate(self)
}
}
func applicationDidFinishLaunching(_ notification: Notification) {
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (allowed, error) in
NSLog("#testapp application did finish launching")
if CommandLine.arguments.indices.contains(1) && CommandLine.arguments[1] == "terminate" {
NSLog("#testapp terminate mode enabled")
self.showNotification()
self.terminate()
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.terminate()
}
}
}
}
func applicationWillTerminate(_ aNotification: Notification) {
NSLog("#testapp terminating…")
}
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void
) {
NSLog("#testapp notification triggered")
self.terminate()
completionHandler()
}
}
Test app available on GitHub at https://github.com/sunknudsen/test-app.
This issue is caused by a bug in macOS Big Sur 11.6.
Everything works as expected in macOS Big Sur 11.6.1 or macOS Monterey.

macOS Swift 3 - Handling notification alert action button

I'm new to Swift (but not to programming). I have simple app that provides an alert based on specific conditionals. I would like to execute a function (or even just set a variable) when one of the buttons is pressed. Ideally, I just need one button, but if for whatever reason, only the notification.actionButtonTitle can have a handler, that's fine with me.
My notification code is currently in a Swift file as a helper.
import Foundation
class NotificationHelper {
static func sampleNotification(notification: NSUserNotification) {
let notificationCenter = NSUserNotificationCenter.default
notification.identifier = "unique-id-123"
notification.hasActionButton = true
notification.otherButtonTitle = "Close"
notification.actionButtonTitle = "Show"
notification.title = "Hello"
notification.subtitle = "How are you?"
notification.informativeText = "This is a test"
notificationCenter.deliver(notification)
}
}
Currently in AppDelegate, this is defined:
let notification = NSUserNotification()
…and I call the notification like this:
NotificationHelper.sampleNotification(notification: notification)
The resulting notification works, as you can see in the screenshot below. However, I cannot seem to listen to the button action. I have tried adding this to the AppDelegate as well as the NotificationHelper file, but I did not have any success with it:
func userNotificationCenter(center: NSUserNotificationCenter, didActivateNotification notification: NSUserNotification) {
print("checking notification response")
}
Any idea of what I'm missing?
Thanks!
You'll need to assign something as the delegate of the NSUserNotificationCenter:
NSUserNotificationCenter.default.delegate = self
If you add this to your AppDelegate and make your AppDelegate conform to NSUserNotificationCenterDelegate:
class AppDelegate: NSObject, NSUserNotificationCenterDelegate {
}

Deep link into macOS app is not recognized

I'm trying to implement a deep link into an macOS application, but nothing seems to work.
So far, my AppDelegate.swift contains the following
func application(app: NSApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
print("opened by link");
return true
}
I also configured the info.plist with URLSchemes beeing my bundle identifier and URLIdentifier beeing simply zst
In a simple html-file I use the following code to test the deep link
Test
My app gets opened (or becomes active when already running), but the print statement is not executed.
What am I doing wrong here?
Thanks to #Ssswift I found a solution.
Used this code:
How do you set your Cocoa application as the default web browser?
and converted it to swift with: https://objectivec2swift.com
works with Swift 3
in AppDelegate.swift added these lines
func applicationDidFinishLaunching(_ aNotification: Notification) {
var em = NSAppleEventManager.shared()
em.setEventHandler(self, andSelector: #selector(self.getUrl(_:withReplyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
func getUrl(_ event: NSAppleEventDescriptor, withReplyEvent replyEvent: NSAppleEventDescriptor) {
// Get the URL
var urlStr: String = event.paramDescriptor(forKeyword: keyDirectObject)!.stringValue!
print(urlStr);
}

Display NSUserNotification when app is active

I am currently making a XIB Menu Bar application that displays a notification using this code:
func showNotification(message:String, title:String = "App Name") -> Void {
let notification = NSUserNotification()
notification.title = title
notification.informativeText = message
NSUserNotificationCenter.defaultUserNotificationCenter().deliverNotification(notification)
}
And calling it like this:
showNotification("\(song)\n\(artist)",title: "Now Playing")
The notification works when the Menu Bar application is hidden away (not shown), however when the user has it shown, the notification does not show.
Is there a way to show the notification while the application is in view?
By default when your application is active, notifications delivered by your app are not shown. To get the expected behaviour, you have to use the user notification center delegate like below :
extension AppController: NSUserNotificationCenterDelegate {
private func setupUserNotificationCenter() {
let nc = NSUserNotificationCenter.defaultUserNotificationCenter()
nc.delegate = self
}
public func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool {
return true
}
}

Swift NSUserNotification doesn't show while app is active

I am new to OSX development and I am making an app which fires a notification when something happens. But it isn't showing the notification when the app is the key app, as it is the default behavior. I want to show them even when the app IS the key app.
However I only found solutions to this matter that were written in objective-c but right now I am working with Swift. I was wondering how I could I implement it with Swift.
To ensure the notifications are always shown you'll need to set a delegate for NSUserNotificationCenter and implement userNotificationCenter(center:shouldPresentNotification:) -> Bool. The documentation says this message is
Sent to the delegate when the user notification center has decided not
to present your notification.
You can implement the delegate in any class of your choosing. Here is an example:
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
func applicationDidFinishLaunching(aNotification: NSNotification) {
NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self
}
func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool {
return true
}