viewDidAppear not firing ever again after app enters foreground - iphone

I have traced a problem in my iPhone app code to the viewDidAppear method not always firing. When you start the app the event fires as expected. However if I close the app using a phone capable of multitasking and reopen in. My viewDidAppear events no longer fire.
My views are loaded from Nibs and I use viewDidUnload to clean up (release and nil all outlets). My views are nested in side and tab bar then navigation controllers. I looks like the events aren't wired up properly when the nibs reload. Any idea on what I'm doing wrong/missing and how I can fix this?
Thanks in advance.
UPDATE I do not mean the event is not fired when the app first comes into the foreground. I mean the event never fires again. Even when changing between tabs or moving though the navigation views.
Example:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"viewDidAppear called");
}
This code is placed in two views, each on different tabs. Each time I swap between tabs "viewDidAppear called" is written to the log. When I close and reopen the app and swap between tabs this no longer happens. Other button events fire normally.

Btw, the viewDidUnload method is really badly named btw -- it's not an 'opposite' to viewDidLoad, it's only called if there was a low memory situation and the view for that controller was unloaded due to not being visible at that time.
(ORIGINAL, NOT SO RELEVANT ANSWER:)
Please see my answer to this similar question:
Why does viewWillAppear not get called when an app comes back from the background?
Basically, viewDidAppear gets called after your UIViewController's view was added to the application's UIWindow heirarchy. Backgrounding then restoring the app doesn't change your view in that respect, so viewDidAppear doesn't get called -- it's correct behaviour, and not a bug. Check out the API docs for UIViewController.

Found it.
While not new to programming I am new to iPhone development. On researching this problem I found it was not recommended to call the viewWillAppear and viewWillDisappear methods manually.
My viewWillDisappear methods resign any keyboards if shown, when my app enters the background it loads a splash screen ready for when the app re-enters the foreground (there is some logic I need to do to work out what the user is shown on restarting the app and I can do this under the splash screen).
As viewWillDisappear is not called when the app goes into the background to make sure no keyboards appeared over my splash screen I was calling viewWillDisapper in the applicationDidEnterBackground method. I guess this also un-registers my events.
By adding viewWillAppear to my applicationDidEnterForeground method my events started firing again. Lesson learned, I will refactor this so I don't call these events manually.
Thanks for the help.

Related

Camera turns black upon resume

My app uses multiple features for Apple's demo project AVCam. Everything works just fine except when I exit the app and go back in it, it doesn't show the camera preview anymore. Does anyone know what piece of code I am supposed to use and where it belongs? I tried searching but a lot of questions relating to android popped up.
You need to reinitialize your camera once the App becomes active again. In your app delegate methods, override, applicationDidBecomeActive and send a notification so your view controller knows that your app became active again.
Pending the notification received, you can reload the viewDidLoad, or move the contents of viewDidLoad to viewDidAppear. There's multiple ways to do this. You can also reload the contents of viewDidLoad in viewWillAppear. There's many many many ways to do this, like I said.

view seems to reload itself

If I stop using my app for a long time then go back to it, it seems like the viewDidLoad method is being called again, even though I never "exited" the app (by pressing the home key twice and tapping the X) nor did I reboot the iPhone. If I just go to the home screen and then open the app again after a short time this does not happen. What is going on?
This has to do with the way that the operating system manages memory and how it deals with having many different apps open at one time. In a short summary, if your app is in the background for a long period of time, eventually, the OS will decide that it is inactive, and the memory associated with its view will be marked for reuse somewhere else where it is more needed. This is the viewDidUnload method in your view controller. Any time the viewDidUnload method is called, the viewDidLoad method will be called again so that you get a chance to reload your view before the user sees it.
Edit:
You cannot rely on this phenomenon happening every x minutes. It will only happen as the OS requires more memory for active apps. If you want to make sure the user always gets updated information when he or she resumes usage of your app, use NSNotificationCenter and register for the UIApplicationDidBecomeActive notification.
You can try to monitor the memory waring. Most of situation like this is memory warning get trigger and viewDidUnload get called after that if the view is not the top most. So when you back to that view, viewDidLoad will get called again.
You can try to override this method in UIViewController and see if memory warning get called. It maybe triggered by some other component in your application.
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}

When to show Alert for Startup and coming out of background?

In my project I show an Alert to the user to indicate an 'empty list'.
Right now, I show it in AppDelegate>applicationDidBecomeActive.
I'm doing this because I want the alert to show if the list is empty
at app startup and when coming out of the background (iOS 4.2 through 5.x).
EDIT:
I use a method in the AppDelegate, and call it with a slight delay, and I still get this notice.
[self performSelector:#selector(checkForNoMessages) withObject:nil afterDelay:1.0];
However, this causes a "wait_fences" notice in the debugger and I'd prefer not to submit to Apple with this notice.
Where is the proper place to put a popup Alert so that it appears:
1) At App startup
AND
2) When the App is coming out of the background?
Do I need the Alert in more than one place?
I recommend writing a method in your AppDelegate or better in your root view controller which shows the message. Maybe with some arguments, so you can reuse it but that's up to you.
If you are following the MVC architecture ask your model about existing entries and trigger the Alert message if necessary. But encapsulate this behavior in a controller as well.
application:didFinishLaunchingWithOptions: and applicationDidBecomeActive: are the places where you want to delegate this task to your controller.
More about iOS Multitasking: https://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
Edit:
Don't forget that you have to call the methods from the main thread.
And do all startup stuff first.
OK - the problem wasn't where I called the alert, it was because it was in a method. Once I moved the code from a method into applicationDidBecomeActive, all is well.

ViewDidAppear Home Button

I have a timer with a countdown. In recent testing, I've noticed that if I hit the home button and return to the app, the timer is off (fewer seconds have ticked off than should).
I've noticed in testing that ViewDid and ViewWill Appear do not fire when re-opening the app. I know that:
- (void)applicationWillEnterForeground:(UIApplication *)application
Fires, but how do I make it specific to certain part of a viewController that was active?
You probably want applicationDidBecomeActive: and applicationWillResignActive:, which are sent to your app delegate. There are also notifications posted (e.g. UIApplicationDidBecomeActiveNotification) you could listen for.
Those are also posted when, e.g., a system alert comes in. If you just want to be told when you're going to the background, try applicationDidEnterBackground: and applicationWillEnterForeground:
See the Apple Docs on lifecycle for details.
Just for the sake of follow up, as the question was answered above.
I had the exact same problem as Eric and then I implemented Jesse's suggestion about using applicationDidBecomeActive: on the delegate. I just wanted to make sure how all the different methods were being called, and I found this:
application:didFinishLaunchingWithOptions: is called at the very start, as expected.
Then, is the main view controller's viewDidLoad turn.
Then viewWillAppear: is called.
Back in the application delegate, applicationDidBecomeActive: is triggered (here I call my reactivateTimer method which I implemented in the main view controller).
The reactivateTimer method is executed.
The last step is the call to the main view controller's viewDidAppear:

quit app in iOS4

I have an old app which did many UI initialization work in viewDidLoad of various views. In iOS4 home button just put the app in background so viewDidLoad won't get called when re-launching the app.
I don't want to put those initialization procedures in viewWillAppear as it is unnecessary to re-initialize the data every time the view appear.
How can I completely quit my app when user press the home button? or any simple way to reload the view controllers that sit inside a tabBarController?
thanks.
There is a key in your app's Info.plist file called UIApplicationExitsOnSuspend, set it to the boolean YES, which will essentially revert the home button's functionality to pre-iOS4 and completely exit your app when the home button is tapped.
Try disabling backgrounding. Apple has this in their documentation
Try to check.
UIApplicationExitsOnSuspend
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html
you have to look up to the UIApplicationDidBecomeActiveNotification i think, but in the uiapplicationdelegate-protocol, there are even some other interesting things for you
or perfectly for you:
UIApplicationWillEnterForegroundNotification as a new notification in ios4 for this problem