I have a split view based app, and would like to listen for some sort of notification for when the root menu is displayed. The reason I want to do this is because the keyboard overlaps the menu, so I would like to hide the keyboard when the menu is displayed.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:<Some Notification Here>
object:self.view.window];
I already have the method to hide the keyboard, I'm just looking for the appropriate notification.
Thanks!
you can post the notification yourself from the root menu. Just subclass it and post the notification on viewDidAppear or viewWillAppear.
The word of warning: if you are targeting iOS 5 and up you should kep in mind the viewWillAppear and viewDidAppear are deprecated in iOS6. use
willMoveToParentViewController or didMoveToParentViewController or -(void)viewWillLayoutSubviews
-(void)willMoveToParentViewController:(UIViewController *)parent{
if (!parent)
//post notification here
}
Also, you can provide nil as a notification name and listen to any possible notification, then NSLog it out, perhaps you can find a useful notification there, just make sure it is documented to futureproof your product.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notificationReceived:) name:nil object:nil];
Related
I want to check orientation of app in the app delegate, is there a viewDidAppear equivalent in the app delegate?
Or where should I place the code to check where the orientation has changed (in the app delegate)
Well you have applicationDidFinishLoading:withOptions: which is your closest thing to a viewDidLoad, but it only runs once when the application first launches and that's it.
If you want to monitor the device orientation outside of a view controller, your best bet it to use the notification center, and register your class as an observer. Something like this should do the trick
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
Then whenever the orientation is changed, the orientationChanged: method will be called.
Just make sure that you unsubscribe when the class is destroyed or deallocated with
[[NSNotificationCenter defaultCenter] removeObserver:self];
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!
In my app, When I press the home button, I pop the application to rootviewcontroller login class. Now, in the previous class, if any alertview comes and without dismissing it I press home button, Problem appears. Next time I tap on app icon to bring it in fore ground, the login screen is there, but on top of it, previous class alertview is also there. How to remove the alertviews on applicationDidEnterBackground?
Have a global (AppDelegate property or singleton) where you simply store the pointer to the last alert view displayed (and clear it when done). If the pointer is non-nil, dismiss it in DidEnterBackground or wherever.
You can also use UIApplicationWillResignActiveNotification,UIApplicationWillEnterForegroundNotification to solve this issue
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(resignActive)
name:UIApplicationWillResignActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(enterForeground)
name:UIApplicationWillEnterForegroundNotification
object:nil];
In resignActive method you can remove the alertviews...
In my applicationWillEnterForeground, I check and send a notification if data refresh is necessary:
[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshModelNotification" object:nil];
The only observer for that particular notification is a particular view controller:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(refreshData:) name:#"refreshModelNotification" object:nil];
That view controller is one of several inside a UITabBarController.
My question is: what happens if that view controller isn't the active tab when the notification is sent?
Thanks in advance.
If the observer is still set for the view controller the view controller will still receive the notification and behave normally except any visual changes to the view controller's view will not be seen
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.