I’ve been trying to get the Notification Center to reply back to the script, but can’t get what is written in the Developer documents. Also, what I’ve read on the internet doesn’t cover the reply back to the script. What I have already is working for sending the notification. When I test the ‘presented’ property of NSUserNotification, I don’t seem to get YES or NO. I’m thinking that I need to set the ‘delegate’. Anyway, here’s what I compiled from some of the things from the internet, my own, and especially from Shane’s posts:
script AppDelegate
property parent : class "NSObject"
property myNotification : missing value
on applicationWillFinishLaunching_(aNotification)
-- send a notification to indicate the application has started, then quit
-- set theDate to current application's class "NSDate"'s |date|() -- current date
set numSeconds to 10
set targetDate to current application's class "NSDate"'s dateWithTimeIntervalSinceNow_(numSeconds)
-- format string from NSDate (ShaneS)
set myFormatter to current application's class "NSDateFormatter"'s alloc()'s init()
myFormatter's setDateStyle_(1) -- 0 = none, 1 = short, 2 = med, 3 = long, 4 = full
myFormatter's setTimeStyle_(2)
set dateAsString to myFormatter's stringFromDate_(targetDate)
-- send notification to NSUserNotificationCenter
my sendNotification_("The Timer",dateAsString,"It's time!","Restart","Stop",targetDate,"Boing")
say "The message was sent."
-- how to check for delivered (presented) and recieved (NSUserNotificationActivationType)?
quit
end applicationWillFinishLaunching_
-- Method for sending a notification
on sendNotification_(aTitle, aSubtitle, aMessage, aActionButtonTitle, aOtherButtonTitle, aDeliveryDate, aSound)
-- make the notification
set myNotification to current application's NSUserNotification's alloc()'s init()
set myNotification's title to aTitle
set myNotification's subtitle to aSubtitle
set myNotification's informativeText to aMessage
set myNotification's actionButtonTitle to aActionButtonTitle
set myNotification's otherButtonTitle to aOtherButtonTitle
set myNotification's deliveryDate to aDeliveryDate
set myNotification's soundName to aSound
-- schedule the notification
current application's NSUserNotificationCenter's defaultUserNotificationCenter's scheduleNotification_(myNotification)
end sendNotification_
on applicationShouldTerminate_(sender)
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate_
end script
What the script does is create a notification with various parameters. One thing to note is that when the user clicks on the action button, the application is rerun. If the user clicks on the ‘other’ button, the notification is removed. Mainly, my question is why don’t I read YES or NO to the ‘presented’ property for now?
PS: Consider that notifications are only presented visibly, when the target application is not frontmost.
If you want the notifications always to be presented, implement also
“delegate method” means that the target class calls those methods at specific moments to inform about a progress
or an asynchronous action.
NSUserNotificationCenterDelegate Protocol provides these methods
“ userNotificationCenter:didDeliverNotification: is sent when the notification is delivered “ userNotificationCenter:didActivateNotification: is sent when the user clicks the action button
“ userNotificationCenter:shouldPresentNotification: is sent when the user notification center has decided not to present your notification. Return YES/true to display the notification regardless. NO/false is the default
If anybody’s interested, here’s the script I ended up with:
script AppDelegate
property parent : class "NSObject"
property myNotification : missing value
property notificationCount: 0
on applicationWillFinishLaunching_(aNotification)
-- initialize
end applicationWillFinishLaunching_
on applicationShouldHandleReopen_hasVisibleWindows_(theApplication, aFlag)
my applicationDidFinishLaunching_(missing value)
return NO
end applicationShouldHandleReopen_hasVisibleWindows_
-- main
on applicationDidFinishLaunching_(aNotification)
-- set the delegate to script
current application's NSUserNotificationCenter's defaultUserNotificationCenter's setDelegate_(me)
-- get target date
set numSeconds to 30
set targetDate to current application's NSDate's dateWithTimeIntervalSinceNow_(numSeconds)
-- format string from NSDate
set dateAsString to my formatDate_(targetDate,1,2)
-- make user info NSDictionary
set notificationCount to notificationCount + 1
set theValue to (notificationCount as string)
set nsDict to current application's NSDictionary's dictionaryWithObjectsAndKeys_("value1", "key1", theValue, "key2", "value3", "key3", missing value)
-- send notification to NSUserNotificationCenter
my sendNotification_("The Timer",dateAsString,"It's time!","Restart","Stop",targetDate,"Boing",nsDict)
say "The message was sent."
return
end applciationDidFinishLaunching_
--
-- Formats NSDate to string using styles
-- 0 = none, 1 = short, 2 = med, 3 = long, 4 = full
on formatDate_(aNSDate, aDateStyle, aTimeStyle)
set myFormatter to current application's NSDateFormatter's alloc()'s init()
myFormatter's setDateStyle_(aDateStyle)
myFormatter's setTimeStyle_(aTimeStyle)
set formattedDate to myFormatter's stringFromDate_(aNSDate)
return formattedDate
end formatDate_
-- Method for sending a notification
on sendNotification_(aTitle, aSubtitle, aMessage, aActionButtonTitle, aOtherButtonTitle, aDeliveryDate, aSound, aDict)
-- make the notification
set myNotification to current application's NSUserNotification's alloc()'s init()
set myNotification's title to aTitle
set myNotification's subtitle to aSubtitle
set myNotification's informativeText to aMessage
set myNotification's actionButtonTitle to aActionButtonTitle
set myNotification's otherButtonTitle to aOtherButtonTitle
set myNotification's deliveryDate to aDeliveryDate
set myNotification's soundName to aSound
set myNotification's userInfo to aDict
-- schedule the notification
current application's NSUserNotificationCenter's defaultUserNotificationCenter's scheduleNotification_(myNotification)
return
end sendNotification_
-- delegate instance methods
on userNotificationCenter_shouldPresentNotification_(aCenter, aNotification)
return yes
end userNotificationCenter_shouldPresentNotification_
on userNotificationCenter_didDeliverNotification_(aCenter, aNotification)
say "Notification Delivered"
set theInfo to aNotification's userInfo
set asRecord to theInfo as record
set theValue to key2 of asRecord
say (theValue as string)
return
end userNotificationCenter_didDeliverNotification_
on userNotificationCenter_didActivateNotification_(aCenter, aNotification)
say "Notification Activated"
-- 0 none
-- 1 contents clicked
-- 2 action button clicked
set userActivationType to (aNotification's activationType) as integer
if userActivationType is 0 then
say "no user activation"
else if userActivationType is 1 then
say "contents clicked"
else if userActivationType is 2 then
say "action button clicked"
else
say "I never get to say anything."
end if
return userActivationType
end userNotificationCenter_didActivateNotification_
--
-- quit
on applicationShouldTerminate_(sender)
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate_
end script
It needs to be run as an application and not from Xcode. No windows.
Edited: I found a minor bug. When I click in the text area of the last window it closed. Needs more testing.
Another bug showed up. A notification was delivered just now. It must be the default delay. I wonder If that was the notification that closed when I clicked the text area.Testing is fun, but I might have to continue tomorrow. I’ll be waiting for more notifications. Think I pressed the text area many times.
Edited: I can’t duplicate clicking on the last notification closing when I click in the text area of the last notification. Maybe it’s a bug in the system.
I think I accidentally swiped the notification window when I had thought that I had clicked in the text area. I’ll need to figure out what to do if the user swipes the window, which makes it open in fifteen minutes (like a fifteen minute snooze). Otherwise everything is working ok. Still need to figure out what to do about removing the delivered items from Notification Center. It depends on what you want to happen when the user clicks the action button.
Here’s the final template like script I ended up with:
script AppDelegate
property parent : class "NSObject"
property myNotification : missing value
property notificationCount: 0
on applicationWillFinishLaunching_(aNotification)
-- initialize
return
end applicationWillFinishLaunching_
-- reopen handler
on applicationShouldHandleReopen_hasVisibleWindows_(theApplication, aFlag)
my applicationDidFinishLaunching_(missing value)
return NO
end applicationShouldHandleReopen_hasVisibleWindows_
-- main
on applicationDidFinishLaunching_(aNotification)
-- set the delegate to script
current application's NSUserNotificationCenter's defaultUserNotificationCenter's setDelegate_(me)
-- get target date
set numSeconds to 30
set targetDate to current application's NSDate's dateWithTimeIntervalSinceNow_(numSeconds)
-- format string from NSDate
set dateAsString to my formatDate_(targetDate,1,2)
-- make user info NSDictionary
set notificationCount to notificationCount + 1
set nsDict to current application's NSDictionary's dictionaryWithObjectsAndKeys_(notificationCount, "NotificationIndex", "value2", "key2", "value3", "key3", missing value)
-- send notification to NSUserNotificationCenter
my sendNotification_("The Notifier",dateAsString,"It's time!","Restart","Stop",targetDate,"Boing",nsDict)
say "Notification sent."
return
end applciationDidFinishLaunching_
--
-- format NSDate to string using styles
-- 0 = none, 1 = short, 2 = med, 3 = long, 4 = full
on formatDate_(aNSDate, aDateStyle, aTimeStyle)
set myFormatter to current application's NSDateFormatter's alloc()'s init()
myFormatter's setDateStyle_(aDateStyle)
myFormatter's setTimeStyle_(aTimeStyle)
set formattedDate to myFormatter's stringFromDate_(aNSDate)
return formattedDate
end formatDate_
-- method for sending a notification
on sendNotification_(aTitle, aSubtitle, aMessage, aActionButtonTitle, aOtherButtonTitle, aDeliveryDate, aSound, aDict)
-- make the notification
set myNotification to current application's NSUserNotification's alloc()'s init()
set myNotification's title to aTitle
set myNotification's subtitle to aSubtitle
set myNotification's informativeText to aMessage
set myNotification's actionButtonTitle to aActionButtonTitle
set myNotification's otherButtonTitle to aOtherButtonTitle
set myNotification's deliveryDate to aDeliveryDate
set myNotification's soundName to aSound
set myNotification's userInfo to aDict
-- schedule the notification
current application's NSUserNotificationCenter's defaultUserNotificationCenter's scheduleNotification_(myNotification)
return
end sendNotification_
-- delegate instance methods
-- force presentation
on userNotificationCenter_shouldPresentNotification_(aCenter, aNotification)
return yes
end userNotificationCenter_shouldPresentNotification_
-- deliver
on userNotificationCenter_didDeliverNotification_(aCenter, aNotification)
say "Notification Delivered"
return
end userNotificationCenter_didDeliverNotification_
-- user activation
on userNotificationCenter_didActivateNotification_(aCenter, aNotification)
say "Notification Activated"
-- 0 none
-- 1 contents clicked
-- 2 action button clicked
set userActivationType to (aNotification's activationType) as integer
if userActivationType is 1 then
say "contents clicked"
my contentsClicked_(aNotification)
else if userActivationType is 2 then
say "action button clicked"
my actionButtonClicked_(aNotification)
else -- userActivationType is 0
say "no user activation"
end if
return userActivationType
end userNotificationCenter_didActivateNotification_
--
on contentsClicked_(aNotification)
-- do something
return
end contentsClicked_
-- gets user info and deletes delivered notification from Notification Center
on actionButtonClicked_(aNotification)
-- delete the notification and send a new one (or some other action)
-- first get info on notification
set theInfo to aNotification's userInfo
set theValue to theInfo's valueForKey_("NotificationIndex")
say (theValue as string)
-- delete notification from notification center
current application's NSUserNotificationCenter's defaultUserNotificationCenter's removeDeliveredNotification_(aNotification)
-- send a new notification
my applicationDidFinishLaunching_(missing value)
return
end actionButtonClicked_
--
-- quit
on applicationShouldTerminate_(sender)
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate_
end script
Added deleting notification from Notification Center (if needed) and eliminated AppleScript coercion of records. I finally learned how to use Dictionaries.