Knowing when the system has gone to sleep in a Menu Extra? - objective-c

I developed a Menu Extra (menulet) for the Mac but I'd like to know if the machine using the Menu Extra has gone to sleep. I implemented a snooze function but since it's a time-based method it's rather unreliable. Any hints or advice would be greatly appreciated!
Thanks!

You probably want to check out NSWorkspaceWillSleepNotification in NSWorkspace.
The trick is, you need to register for the notifications on NSWorkspace's notificationCenter, not the default one. See Technical Q&A QA1340.
Sample code:
- (void) receiveSleepNote: (NSNotification*) note
{
NSLog(#"receiveSleepNote: %#", [note name]);
}
- (void) fileNotifications
{
// These notifications are filed on NSWorkspace's notification center, not the default
// notification center. You will not receive sleep/wake notifications if you file
// with the default notification center.
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:#selector(receiveSleepNote:)
name: NSWorkspaceWillSleepNotification object:nil];
}

Related

Code on window closing in App Delegate?

I have a Mac application where I would like to save some values when the window closes. However, I can't figure out how to do this. I have the application delegate controlling the main window (which may not be the way you are supposed to do it, and I probably shouldn't have done it this way if what I've read previously is correct) and I can't figure out for the life of me how to do this! I believe it can be done using a NSWindowController, but can you do it in the app delegate? Thanks!
Use NSWindowWillCloseNotification.
- (void)applicationWillFinishLaunching:(NSNotification *)notification {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(windowWillClose:) name:NSWindowWillCloseNotification object:window];
}
- (void)windowWillClose:(NSNotification *)notification {
// Your code for saving data
}

UIKeyboardWillChangeFrame notification not sent when moving undocked keyboard

I am trying to make a toolbar that is always above the keyboard, pretty much like in Apple's native Messages app. If you take a closer look at that app on the iPad, try undocking the keyboard and the dragging it around by holding than button in its bottom right. You will notice that Apple's toolbar tracks the keyboard's position quite nicely.
Trying to replicate that behavior, I subscribed to both the keyboard-will-change-frame and keyboard-did-change-frame notifications. However, to my disappointment I found that the first one is sent when the user starts the dragging, and the latter is sent when the keyboard snaps to its final position, but there are no notifications I could find that are sent in between. Am I missing something? Here's what I am talking about:
This is the code I use to subscribe to notifications:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil];
These are my listener functions:
- (void)keyboardWillChangeFrame:(NSNotification *)notification{
NSLog(#"will change");
// [self alignToolbarForKeyboard:notification action:#"will_change_frame"];
}
- (void)keyboardDidChangeFrame:(NSNotification *)notification{
NSLog(#"did change");
// [self alignToolbarForKeyboard:notification action:#"did_change_frame"];
}
I commented out the call both listener functions make to make sure it's not blocking anything. Is there a notification type I do not know of? I did look at the UIWindow reference but couldn't find anything beyond what I already have. Just to make sure, I also checked whether the show/hide notifications are sent during the movement. They aren't.
Any ideas? Thanks!

Execute code when app reopens

I have a Single View Application. When I hit the home button and ‘minimise’ the application I want to be able to execute code when the user reopens it.
For some reason viewDidAppear and viewWillAppear do not execute when I minimise and reopen the application.
Any suggestions?
Thanks in advance
sAdam
You can either execute code in the app delegate in
- (void)applicationDidBecomeActive:(UIApplication *)application
or register to observe the UIApplicationDidBecomeActiveNotification notification and execute your code in response.
There is also the notification UIApplicationWillEnterForegroundNotification and the method - (void)applicationWillEnterForeground:(UIApplication *)application in the app delegate.
To hook up notifications add this at an appropriate point
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
Define a the corresponding method
- (void)didBecomeActive:(NSNotification *)notification;
{
// Do some stuff
}
Then don't forget to remove yourself an observer at an appropriate point
[[NSNotificationCenter defaultCenter] removeObserver:self];
Discussion
You most likely only want your viewController to respond to events whilst it is the currently active view controller so a good place to register for the notifications would be viewDidLoad and then a good place to remove yourself as an observer would be viewDidUnload
If you are wanting to run the same logic that occurs in your viewDidAppear: method then abstract it into another method and have viewDidAppear: and the method that responds to the notification call this new method.
This is because since Apple implemented "Multitasking", apps are completely reloaded when you start them again, just as if you had never closed them. Because of this, there is no reason for viewDidAppear to be called.
You could either implement
- (void)applicationWillEnterForeground:(UIApplication *)application
and do there what ever you want. Or you register for the notification UIApplicationWillEnterForegroundNotification in your view controller. Do this in viewDidLoad:
[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myAppWillEnterForeground)
name:UIApplicationWillEnterForegroundNotification object:nil];
And of course implement the specified selector and do there what you want.
I am not sure how the answer by #Paul.s performs the OP request since registering UIApplicationDidBecomeActiveNotification will be executed twice:
When launching the app
When application goes into the background
A better practice will be to decouple those events into 2 different notifications:
UIApplicationDidBecomeActiveNotification:
Posted when the app becomes active.
An app is active when it is receiving events. An active app can be said to have focus. It gains focus after being launched, loses focus when an overlay window pops up or when the device is locked, and gains focus when the device is unlocked.
Which basically means that all logic related to "when application launched for the first time"
UIApplicationWillEnterForegroundNotification:
Posted shortly before an app leaves the background state on its way to becoming the active app.
Conclusion
This way we can create a design that will perform both algorithms but as a decoupled way:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(yourMethodName1) name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(yourMethodName2) name:UIApplicationDidBecomeActiveNotification object:nil];
This because you don't redraw your view. Use applicationWillEnterForeground in the AppDelegate instead. This should work fine for you.

Suspending keyboard when user press on home button?

I am developing an application were everything is working fine, except one i.e. when user press on home while keyboard is in active and again opens my application the view frame bounds are changing and moving out of bounds. My expected result is keyboard should get suspended or the view should stay in the same position when it is come back from background to foreground with keyboard in-active state.
I hope people understand my scenario and reply ASAP.
Thanks.
I have found the solution to my question, i hope people can use my solution. Below is the code what I have done,
Add the below line of code in your RootViewController file (i.e. which view is coming at first when you open your APP).
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:UIApplicationDidEnterBackgroundNotification object:nil];
And then add a private method as below
- (void) receivedNotification:(NSNotification *) notification
{
if ([username isFirstResponder])
{
[username resignFirstResponder];
}
else if ([password isFirstResponder])
{
[password resignFirstResponder];
}
}
I hope it help some body,Thank u.
Further assistance please see the mentioned link,
there is a method in the app delegate
- (void)applicationDidEnterBackground:(UIApplication *)application
this method is fired when you press the home button.
do the necessary changes(textField resignFirstResponder) in this method and it should work fine i guess.
EDIT here's the code
in the class where you have your textfield create a method
-(void)performWhenHomeBtnprssed
{
[MytextField resignFirstResponder];
}
then in
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[myClassObj performWhenHomeBtnprssed];
}
also i agree with #valexa you should find the root cause of the problem
In software development it is always better to address the root causes than to patch the effect, in your case there are problems with the positioning of your views and you should address that, foreground/background cycling should not affect the views positioning.

Detecting if ANY window is being dragged

Is there a way (without using any undocumented API) to figure out if ANY window (not just the application from which the code is running from) is being dragged?
I can use
[NSEvent addGlobalMonitorForEventsMatchingMask:]
but this is just for general dragging and there's no way to tell if a window is beign dragged or not.
Thanks!
Update: I think the answer might lie with these two functions:
CGSGetWindowBounds
CGSNewRegionWithData
If someone can tell me what these functions do and where I can find the documentation for them, it would be great! Thanks.
Your only viable, system-supported API is the Accessibility Framework. You can get notifications this way for other applications' windows but access to read/modify is limited to position/size.
I'm not sure if there's a better approach, but here's one way to do it:
Create an BOOL ivar that tracks whether a window is being moved or not. Then register for the NSWindowWillMoveNotification and NSWindowDidMoveNotication notifications:
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(windowWillMove:) name:NSWindowWillMoveNotification object:nil];
[nc addObserver:self selector:#selector(windowDidMove:) name:NSWindowDidMoveNotification object:nil];
Then handle the notifications and set the ivar appropriately:
- (void)windowWillMove:(NSNotification*)notification
{
windowBeingDragged = YES;
}
- (void)windowDidMove:(NSNotification*)notification
{
windowBeingDragged = NO;
}
Now you can just check the value of the ivar (windowBeingDragged in this case, to check if a window is being dragged).