What action is invoked when today widget center is being closed? - objective-c

I need to find the way to respond to notification centre being closed/hidden. The reason is that I have a pop up NSMenu in that widget, and if you open it and then close entire notification centre, pop up menu remains on the screen.
I have already tried to implement NSWindowDelegate but there is no such event that defines closing of today widget centre. The closest things I found are -windowDidMiniaturize: and
-windowWillClose:. But when side bar closes they are not invoked.

Finally I have found needed method in NSWindowDelegate protocol.
First step is to add self (in that case it is viewController) as an observer for desired method: windowDidResignKey:
-(void)viewWillAppear {
//set this view controller delegate for selector windowDidResignKey
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:self.view.window];
}
And second is to implement this method:
- (void)windowDidResignKey:(NSNotification *)notification {
//If window did resign key (close today center) - close menus
if(_sourceLanguageMenu)
[ _sourceLanguageMenu cancelTracking];
if(_targetLanguageMenu)
[ _targetLanguageMenu cancelTracking];
}

Related

Double-click action for menu bar icon in Mac OSX

I'm writing a small Mac OSX app that displays a menu bar icon. When clicked, a menu pops up.
I'd like to have a "default" action for the menu bar icon. Basically, to execute an action when double-clicking it, without having to select the action from the menu.
I looked over the Apple docs and there's is such a thing in NSStatusItem called doubleAction, but it's soft deprecated and does not (seem to) work. More over, the docs it says to use the button property, but trying to do so results in the compiler error shown below:
Any code or guidance are much appreciated, thanks!
The situation as it stands today (Xcode 7.3.1, OSX 10.11.4):
the doubleAction of NSStatusItem is deprecated (and NOT actually working).
Apple tells you to use the button property - but there's no header for doubleAction (I wonder if the implementation exists). Oh, it's also read-only.
there are no other options regarding left/right/double click in any of the NSStatusItem's properties.
The workaround: create a category for NSButton (the exact same that Apple was talking about) and implement a custom click handler that posts a notification when a double click was detected, like the following:
#implementation NSButton (CustomClick)
- (void)mouseDown:(NSEvent *)event {
if (self.tag != kActivateCustomClick) {
[super mouseDown:event];
return;
}
switch (event.clickCount) {
case 1: {
[self performSelector:#selector(callMouseDownSuper:) withObject:event afterDelay:[NSEvent doubleClickInterval]];
break;
}
case 2: {
[NSRunLoop cancelPreviousPerformRequestsWithTarget:self];
[[NSNotificationCenter defaultCenter] postNotificationName:#"double_click_event" object:nil];
break;
}
}
}
- (void)callMouseDownSuper:(NSEvent *)event {
[super mouseDown:event];
}
#end
As you can see, this handler only handles NSButton instances that have a specific tag value.
When a click is detected, I defer the call to super for handling by the system's double-click interval. If within that time I receive another click, I cancel the call to super and treat it as a double-click.
Hope it helps!
You can use NSApp.currentEvent
self.statusItem.button.target = self;
self.statusItem.button.action = #selector(clickOnStatusItem:);
...
- (void)clickOnStatusItem:(id)sender {
if (NSApp.currentEvent.clickCount == 2) {
// Double click on status item
}
}
also, you can process a right mouse button on the status bar item

Collapsing A Collection View Cell

I have a scroll view, inside a collection view cell. The scroll view has a class of its own (ClassA), as does the collection view (ClassB). When you tap the index row, it expands. Sweet, works just fine. Only problem is, you have to tap on the index row to collapse the cell. Since there is a UIScrollView hanging out in the cell, tapping on it won't collapse the cell. So, what I did was create tap detection in the scroll view. The tap detections selector then handles collapsing the cell via notifications:
Class A:
- (void)singleTap:(UITapGestureRecognizer *)gesture {
// Post a notification to collapse
[[NSNotificationCenter defaultCenter] postNotificationName:#"collapseCell" object:nil];
}
Class B:
-(void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(deselectItemAtIndexPath:animated:)
name:#"collapseCell" object:nil];
}
Error: 'NSInvalidArgumentException', reason: '-[CollectionViewController deselectItemAtIndexPath:animated:]: unrecognized selector sent to instance 0x7caa
That NSNotificationis not doing what you think it's doing. Its not calling or trying to call the UICollectionView's delegate method, deselectItemAtIndexPath:animated:. Its actually looking for a different method, but with the same signature as the UICollectionViews delegate method.
Make a test method, call it something simple and see if that works to confirm what I think is happening.

Load Title ViewController When applicationDidBecomeActive:

I've created an app that has two viewcontrollers. The app opens to a title screen (general UIViewController titled 'Title') with a segue connection to the second view that is a custom class (OSViewController titled 'MapView'). As it is, the app suspends when entered into the background state so it opens right where you left off which is typically in MapView.
I want to know what I need to do to have the app start at the title screen when it becomes active. Preferably, I'd like it to open to the title screen if it is inactive for more than 1 minute. From what I've been reading, it seems like I would make a call in applicationDidBecomeActive: method in my AppDelegate to code this in. Please provide me the code to put in the applicationDidBecomeActive: method (if that's the right place to put it) that will reopen my app to the title screen when transitioning from the inactive state to the active state. My app is almost finished but I'd like to fix this issue and I don't have a lot of experience dealing with app states. Thanks in advance for your time.
If you need more information just ask.
You can also register a class as an observer of the "didBecomeActive" notification. You should place this in the viewDidLoad or the init method of your class.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
In this case, willBecomeActive: is a method that you have defined in your class that get's called when the app becomes active again. That might look something like this:
- (void)willBecomeActive:(NSNotification *)notification {
if (self.navigationController.topViewController == self) {
[self.navigationController popToRootViewControllerAnimated:YES];
}
}
You'll also need to add this in your viewDidUnload method
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
EDIT:
Thanks #AMayes for the advice. I don't believe key/value observing is necessary in this instance.

Reloading NSTableView on re-focus

In my application, I have a NSWindow that has a NSTableView object and a few buttons. When the user presses the "new" button, an "ItemAdd" NSWindowController is activated where the user types in attributes for the item to be added to the NSTableView.
My question is this: since NSTableView requires reloadDatato update its view, how do I call reloadData after the ItemAdd window closes and focus shifts back to the NSWindow with the NSTableView.
Thanks for the help!
You could put reload data in a notification handler:
Put this in an initialization method of an object that you want the notification to get called on:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didBecomeMainWindow) name:#"NSWindowDidBecomeKeyNotification" object:nil];
Then make a method something like this:
- (void) didBecomeMainWindow
{
[tableView reloadData];
}
You can subclass the NSWindow and override the following method:
- (void)becomeKeyWindow

Refresh NSView content when the view is displayed with MAAttachedWindow

Im my application, I display a NSView when a user click on an icon in the systemstatusbar.
This NSView is displayed with MAAttachedWindow.
My question is : how to refresh the NSView content when the attachedWindow is displayed (makeKeyandorderFront)
I've tried to refresh the content in the awakeFromNib method,but it works only once.
Could anyone help me?
thanks
The solution I've found:
I've added a observer in my view:
I've set the object to [selft window] to listen the NSWindowDidBecomeKeyNotification notification of the MAAttachedwindow.
-(void)awakeFromNib
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:[self window]];
}
-(void) windowDidBecomeKey:(NSNotification *)note
{
// Do refresh here
}
The reason -awakeFromNib only works once is presumably because you're only loading the assembly from the xib once and keeping it around.
Presumably whatever action actually shows your view in the MAAttachedWindow instance is the ideal place to "refresh" it before display, ie your own call to -makeKeyAndOrderFront:.
So: What have you tried?