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];
Related
Given this code in the viewDidLoad:
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(keyboardWillShow:) name:
UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:#selector(keyboardWillHide:) name:
UIKeyboardWillHideNotification object:nil];
I'm asking myself if I need to delete the observers when I unload the view (or something similar).
It looks a bit like this question, but that question does not discuss if dealloc is deprecated since the use of ARC (edit: see comments in accepted answer).
But since ios updates all the time and I have no clue if you still would need to call dealloc and I've never seen a piece of code how to do this (delete the observers that is), some help would be appreciated :)
Yes, you do. Override dealloc in your view controller like so:
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
In general, you should remove an observer from a notification center when the observer is no longer needed -- either you don't need it to continue observing, or the object itself is being deallocated. You don't need to remove an object observing UIKeyboardWillHideNotification simply because the keyboard is going away, but you do need to remove it if you're getting rid of the object itself.
Consider what would happen if you didn't remove the observer before it was deallocated: if the notification it was watching for ever occurred, the notification center would try to send a message to that object. That would cause either a crash or some behavior that you don't expect, since the pointer the notification center used to send the message no longer points to the object that's supposed to observe the notification.
It is always good to have your notification observer's unregistered while they are not required.
Since your observer deals with Keyboard which is a visual element, have it unregistered, i.e. removed from observer on viewDidDisappear and have it re-register in viewWillAppear (something which i follow.).
This is required coz, in case you are pushing a new view controller over the one you are using, the observer will still be registered and can cause erroneous behaviour, and sometimes, if your view controller get deallocated, the notification will still have the observer registered and can lead to crash. Coz notification centre defaultCenter is a singleton instance for process and will be there for its lifetime.
Post iOS 6.0 you can call it in viewDidUnload. But iOS 6.0 that is deprecated.
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];
Im working on an ios app, ios 5+ , using xcode and objective c. Ok currently messing with nsnotifications and i just need some clarifications as im a wee bit confused.
Lets say i have a view controller that i add an observer to like so
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showContent:) name:kTPSShowContentNotification object:self];
where the object is set to self. I took this to mean that it is only looking from that notification if sent from that object. am i wrong on that?
elsewhere in code I am positing a notification like so
[[NSNotificationCenter defaultCenter] postNotificationName:kTPSShowContentNotification object:currentVC];
where currentVC is the view controller that has the observer set up initially.
I thought this is all that was needed to catch that notification as the post is telling the notification center to send it from that view controller. but it fails to catch it and im unsure as to why. If when adding the observer i set the object as nil then it catches it but so does all the other viewcontrollers (if any ) that have observers for that notification too. Is there any way around this ? am i approaching this completely wrong?
To receive notification only from theObjectSendingNotification object you should write:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showContent:) name:kTPSShowContentNotification object:theObjectSendingNotification];
and the object sending notification should send it in this way
[[NSNotificationCenter defaultCenter] postNotificationName:kTPSShowContentNotification object:self];
If I'm getting this right, you want to post and get a notification from the same controller. So you can do something like this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showContent:) name:kTPSShowContentNotification object:self];
[[NSNotificationCenter defaultCenter] postNotificationName:kTPSShowContentNotification object:self];
But it should work indeed if your currentVC ivar is pointing to the very same controller. The fact that you say it doesn't work makes me believe that it is not pointing to the same instance of your controller.
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.
- (void)applicationWillResignActive:(UIApplication *)application {
NSLog(#"resigning active status...");
}
i have tried hardware-lock in iphone simulator but this isn't called. I do want to call it in another UIviewcontroller class not in the appdelegate itself.I also added in the viewController's header File.
According to the documentation, the "applicationWillResignActive" method will get called if the device is locked.
As such pressing Command-L (or "Hardware" >> "Lock"" in the menu) will cause the iPhone simulator to lock and hopefully trigger this method.
I could only get this code to work in the AppDelegate file as well.
You could trying adding your view controller as an observer using the NSNotificationCenter,
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(foo) name:#"AppResigned" object:nil];
Then in the applicationWillResign post the notification,
[[NSNotificationCenter defaultCenter] postNotificationName:#"AppResigned" object:nil];
Hope that helps!