How to detect when user opens the OS X Notification Center? - macos

How do I detect when a user opens the OS X Mountain Lion Notification Center?
Is there an NSNotification (ugh, very similar term for a different thing) which I can observe?

I don't know of any officially documented solution or notification (let me know!), but this appeared to work (at least on OS X 10.10) when I tested it, so long as my application was in the foreground/had the frontmost window I believe.
Add your object as an observer:
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationCenterOpened:) name:#"com.apple.HIToolbox.beginMenuTrackingNotification" object:nil];
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationCenterClosed:) name:#"com.apple.HIToolbox.endMenuTrackingNotification" object:nil];
Add methods similar to the following to your object, making sure to check for the correct ToolboxMessageEventData number (4927), for example:
- (void)notificationCenterOpened:(NSNotification*)notification {
if ([notification.userInfo[#"ToolboxMessageEventData"] isEqual: #4927]) {
NSLog(#"Notification center opened");
}
}
- (void)notificationCenterClosed:(NSNotification*)notification {
if ([notification.userInfo[#"ToolboxMessageEventData"] isEqual: #4927]) {
NSLog(#"Notification center closed");
}
}
Let me know if that does or doesn't work for you.
Nevermind - upon restart/log-off + log back in, the ToolboxMessageEventData appears to change.

Related

NWSWindow events sequence when NSWindow closes?

Can Anyone give a list of NWSWindow events sequence when NSWindow closes. More specifically which is the last notification that a NSWindow that closes sends. Apple docs are very sparse on any sequence stuff.
The messages sent to a window when closing are – windowShouldClose: and – windowWillClose:. These are sent to the window's delegate and conform to the NSWindowDelegate protocol.
Also you can register to receive NSWindow's notifications such as NSWindowWillCloseNotification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(windowWillCloseNotification:) name:NSWindowWillCloseNotification object:self.window];
- (void)windowWillCloseNotification:(NSNotification*)notification
{
// ... do something, save information...
NSWindow *window = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:window];
}

OS X: Show interface of application agent (UIElement)

How do I make the interface for an application that has 'Application is agent (UIElement)' set to yes reappear?
The interface shows up the first time I start the app, but if I close the window, and the click on the app's icon then nothing happens. I guess that it's because OS X is trying to start the app again, and there is some mechanism preventing that. What I would like is this:
The first click on the app's icon should launch the app and show the interface.
If the interface has been closed down (but the app is still running in the background) a subsequent click on the icon should just show the interface.
If the interface is already shown a click on the icon should simply move the window to the foreground.
Here is a way you can do it:
1) add + initialize method to your app delegate
+ (void)initialize
{
// check if there is a running instance of your app
NSArray * apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:[[NSBundle mainBundle] bundleIdentifier]];
if ([apps count] > 1)
{
//post notification to it to update inteface
[[NSDistributedNotificationCenter defaultCenter] postNotificationName:#"updateInterface" object:nil];
//quit current instance of the app, coz you don't need two apps running continiously
exit(0);
}
}
2) Register your app for the notification
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:#selector(updateInterface:) name:#"updateInterface" object:nil];
}
3) Add updateInterface method
- (void)updateInterface:(NSNotification *)aNotification
{
// handle your interface here
// ....
// move your app forward
[NSApp activateIgnoringOtherApps:YES];
}
I found the answer here: Closing Mac application (clicking red cross on top) and reopening by clicking dock icon.
- (BOOL)applicationShouldHandleReopen:(NSApplication*)theApplication
hasVisibleWindows:(BOOL)flag
{
[self.window makeKeyAndOrderFront:self];
return YES;
}

How to hook the OS X dictionary

on osx lion, you can control-command-d or triple-tap on a word that your mouse is pointed to in any app to launch a popover dictionary. i want to make an app to track the words a user is looking up in the dictionary.
how do i observe the event where the user does control-command-d or triple-tap to launch the popover dictionary?
I understand that the specific API for this is HIDictionaryWindowShow.
You can use popoverDidShow:
- (void)awakeFromNib {
NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self selector:#selector(popoverDidShow:)
name:NSPopoverDidShowNotification object:nil];
}
// dictionary is shown or another NSPopover
- (void)popoverDidShow:(NSNotification*)notify {
//your code
}

NSDistributedNotifications not distributed between instances of (same) app(s)

On 10.7.2 I have trouble getting standard NSDistributedNotifications to work out of the box.
Even when brought back to just (Full XCode version at https://github.com/dirkx/Example-NSDistribtuedNotification-Failing) to something as simple as below I get:
Splendidly working notifications 'locally' (Like with a NSNotificationCenter) but
No inter-app comms when I start the app up twice (e.g. from the command line)
No notifications when another apps registers for this (or for nill)
No debug/info in the distnoted daemon logs either.
What am I missing ?
NSString * kSayNotification = #"org.webweaving.sayExample";
// Send a Distributed Notification on button press.
//
-(IBAction)buttonChange:(NSButton *)sender {
NSString * str = (sender.state == NSOnState) ? #"Yes" : #"No";
[[NSDistributedNotificationCenter defaultCenter]
postNotificationName:kSayNotification
object:str
];
}
// Update a label on receiving a Notification.
//
-(void)notif:(NSNotification *)nf {
.. snipped time string ...
// Textfield with the time of arrival and the value passed in the notification.
//
textField.stringValue = [NSString stringWithFormat:#"%#: %#",
dStr, (NSString *)nf.object
];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Register for the notifications.
//
[[NSDistributedNotificationCenter defaultCenter]
addObserver:self
selector:#selector(notif:)
name:kSayNotification
object:nil];
}
As an aside - notification watcher (https://github.com/melo/notification-watcher) does not show the Notifiactions - but the notifications are processed within the app.
Turns out that when there are no other reasons for CFRunLoop to return - the messages are queued indefinitely. This seems by design.
I found three work arounds for this - none of which is that nice - they both involve
adding a deliverImmediately:YES to the posting,
a deliverImmediately: with NSNotificationSuspensionBehaviorDeliverImmediately to the observer or
setting a timer to intentionally interrupt the runLoop every seconds.
Obviously - none of this comes cheap.
Dw

Application Will Enter Foreground Notification and memory

I'm adding my View Controller as a listener to UIApplicationWillEnterForegroundNotification in my viewDidLoad function (as recommended on previous questions here):
if(&UIApplicationWillEnterForegroundNotification != nil)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myFunc) name:UIApplicationWillEnterForegroundNotification object:nil];
}
}
The problem is that when debugging the application through Instruments it appears this line of code is extremely memory consuming. Any thoughts as to why and how to make it more effective?

Resources