Is there an available view controller method that is called when the user presses the lock button? I'm looking for something like viewDidDisappear: or viewWillDisappear:, but specific to the case of the lock button being pressed.
A notification called UIApplicationDidEnterBackgroundNotification is posted when the user locks their phone. Here's how to listen for it:
In viewDidLoad: of your ViewController:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(screenLocked) name:UIApplicationDidEnterBackgroundNotification object:nil];
Then, define a method (mine was called screenLocked above) and write code you want to be executed when the screen is locked.
-(void)screenLocked{
//do stuff
}
Also, to do some necessary cleanup, add this method to your ViewController too.
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
}
Try this :
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateInactive) {
NSLog(#"Sent to background by locking screen");
} else if (state == UIApplicationStateBackground) {
NSLog(#"Sent to background by home button/switching to other app");
}
}
Related
I have app that send local notifications.
So I have two scenarios.
Application is in foreground, notification center is dragged out. Notification is recived. Notification center is being hidden.
Application is in foreground, notification center is dragged out. Notification is recived. Notification is selected.
My code to handel notifications
AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILocalNotification* notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
//When App is launched from notification
[self setupLocalNotification:notification.userInfo];
}
-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
NSLog(#"USER INFO %#",notification.userInfo);
[self setupLocalNotification:notification.userInfo];
}
-(void)setupLocalNotification:(NSDictionary*)userInfo {
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if ( state == UIApplicationStateInactive || state == UIApplicationStateBackground){
[[NSUserDefaults standardUserDefaults] setObject:userInfo forKey:#"localNotification"];
//This is for situation when I'm deep in navigation controller and this also trigger viewWillAppear in ViewController
[[((MainPanelViewController*)[[self window] rootViewController]) startNC] popToRootViewControllerAnimated:false];
} else {
//something
}
}
** MainPanelViewController**
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//This is for situation when currently in ViewController
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(beacomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self checkLocalNotification];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (BOOL) checkLocalNotification{
NSDictionary* userInfo = [[NSUserDefaults standardUserDefaults] objectForKey:#"localNotification"];
if (userInfo != nil) {
NSLog(#"Notification");
[self performSegueWithIdentifier:#"ShowNotification" sender:self];
return true;
}
return false;
}
Problem
I don't know how to distinct those two situations. Because every time notification is received when App is inactive then method performSegueWithIdentifier is being called.
I have 2 observers registered. One of them is in appDelegate and the other is in myViewController. When I am in myViewController, I just expect to get two notifications, one from appDelegate which executes some method globally, the other one from myViewController which executes some other method. But, only the one in appDelegate gets called. If I remove the observer in appDelegate, the observer in myViewController gets called. Actually, I can just use the observer method in appDelegate and find out the current view controller and execute the code of the method in myViewController. But, I just don't wanna mess appDelegate. The same code for both of them but I remove the observer in myViewController when viewWillDisappear() method gets called. Any ideas? Thanks.
appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:#"someName"
object:nil];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"someName"
object:nil
userInfo:someUserInfo];
}
- (void)someMethod:(NSNotification *)notification
{
// gets called
}
myViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:#"someName"
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"someName"
object:nil];
[super viewWillDisappear:animated];
}
- (void)someMethod:(NSNotification *)notification
{
// not called
}
In the code below you're posting before observing
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"someName"
object:nil
userInfo:someUserInfo];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:#"someName"
object:nil];
}
* Original *
Plenty of possible issues here:
one the notification Name could be spelt wrong = #"someName" - If this is going to be observe red from other classes, think about creating an
in a .h (that both classes import)
include
extern NSString * const XXXSomeNameForSomeNotification;
in the corresponding .m
NSString * const XXXSomeNameForSomeNotification = #"someName";
That's one way to ensure they're all observing/posting the right notification
If that's not your issue then try adding observing the notification from the viewDidLoad or another method that's called prior to viewDidAppear as it could be that it's not observing you notification when it's actually posted. Add break points to observe this.
Looks like, Your notification is posted before view is loaded. See adding some logs.
OR try this -
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[[NSNotificationCenter defaultCenter] postNotificationName:#"someName"
object:nil
userInfo:someUserInfo];
});
I think as per you posted code the reason is
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"someName"
object:nil];
[super viewWillDisappear:animated];
}
The method above will remove the notification observing if the current view is not on screen.
Also you may want to move the
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"someName"
object:nil];
to
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"someName"
object:nil];
}
that way you only stop observing the notification when you remove the view controller form memory. You may want to check in the method that's called if you're on screen.
I need to pause the game before my game goes to background, so when it comes to foreground again I see the pause dialog in my game. To show pause dialog I have a scene method. How to call scene method right before application goes to background? I see that the following method is the right place:
-(void) applicationDidEnterBackground:(UIApplication*)application
{
if( [navController_ visibleViewController] == director_ )
[director_ stopAnimation];
}
Should I just get the scene from director runningScene, cast it to my scene class and then send pause message to it or that way is ugly?
In this scenario, I think Notifications are the cleanest and safest option. You can just post a notification from applicationDidEnterBackground and receive wherever you want to perform certain actions like:
In App Delegate:
- (void)applicationDidEnterBackground:(UIApplication*)application {
[[NSNotificationCenter defaultCenter] postNotificationName:#"EnteringBackground" object:nil];
}
In GameScene:
- (void)onEnter {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showPausePopup) name:#"EnteringBackground" object:nil];
}
- (void)onExit {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)showPausePopup:(NSNotification*)notification {
// Code to show popup
}
I registered my main view controller for listening to UIApplicationDidBecomeActiveNotification because I want to display a UIAlertView each time the user enters my app :
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
It's working like a charm, my only problem is if my app gets interrupted (by an UIAletView, such as a calendar event, or a popup asking for picture access confirmation), the notification gets called once the alert view's dismissed.
Any idea on how to detect ONLY when my app comes back from background mode ?
why don't you use AppDelegate method,
- (void)applicationWillEnterForeground:(UIApplication *)application
{
//do whatever you want when app comes from background to foreground
}
I know this is an old thread, but there is a UIApplicationWillEnterForegroundNotification. Works like this:
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(myMethod)
name:UIApplicationWillEnterForegroundNotification
object:nil];
Best regards,
Gabriel Tomitsuka
Check state (active/background) of your application by following code:
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateActive)
{
/// your stuff of code:
}
Above code might be useful in your case:
I'm developing an iOS app with latest SDK.
It's a fullscreen app.
I have a method on viewWillAppear method that has to be called every time the apps comes from background.
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self setUpVideo];
}
On setUpVideo I set up AVCaptureVideoPreviewLayer because I lose the video when the apps come back from background.
As I have read, viewWillAppear isn't called when the apps come back from background and now, I don't know where to put that code.
On this question, occulus suggest to use [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doMyLayoutStuff:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil]; but it doesn't work for me.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(setUpVideo:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
}
Any advice?
Observe UIApplicationWillEnterForegroundNotification instead.
- (void)viewDidAppear {
[super viewDidAppear];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(enterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
// ...
}
- (void)enterForeground:(NSNotification *)notification {
// do stuff
}
Don't call viewWillAppear: directly from the enterForeground: method. Instead move all required code to a separate method and call that from both viewWillAppear: and enterForeground:.
applicationWillEnterForeground will trigger when app comes from background
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
Additionally, you can use UIApplicationDidBecomeActiveNotification for firing some method
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(handleMethod:)
name: UIApplicationDidBecomeActiveNotification
object: [UIApplication sharedApplication]];
Try posting this notification from
- (void)applicationDidBecomeActive:(UIApplication *)application of AppDelegate(or observe corresponding notification which is better)