My app delegate method applicationDidBecomeActive: is getting called twice for the first time launch of the application. I have some portion of code which I want to execute only once & that I have put into applicationDidBecomeActive:
What should I do?
I got the issue. I am using Location Services. When launching for the first time after I tap on "OK" on the location services alert, my applicationDidBecomeActive gets called one more time which is the normal iOS behavior.
If you want to call your code only once when app becomes active, try calling it from two methods.
didFinishLaunchingWithOptions
applicationWillEnterForeground
instead of calling it only from applicationDidBecomeActive.
This is because of location or push notification alert.
After the native location/push notification has been dismissed, applicationDidBecomeActive will be called.
I don't know if this will help, but I just had the same issue with a totally simple app that doesn't use Location Services, and I found out it's an illusion. Look at the logging messages I got:
2012-12-22 10:47:45.329 Bizarro[10416:907] start applicationDidBecomeActive:
2012-12-22 10:47:45.333 Bizarro[10416:907] end applicationDidBecomeActive:
2012-12-22 10:47:45.329 Bizarro[10416:907] start applicationDidBecomeActive:
2012-12-22 10:47:45.333 Bizarro[10416:907] end applicationDidBecomeActive:
Look closely. Look at the times. The first and third messages have the same time. The second and fourth messages have the same time. They are the same messages! It's an Xcode bug; it has nothing to do with my code. Xcode is reporting the same log messages twice.
In my case, I was able to prevent this by turning off all Behaviors for Running -> Generates Output.
What about:
Increment on applicationDidBecomeActive
Decrement on callback events of permissions requests or other alerts that trigger another applicationDidBecomeActive when closed.
With Xcode 6 there's a new reason this can happen: when you launch an app in a resizable simulator, applicationDidBecomeActive: will get called twice.
It launches the app with the default size class, and then applies the size you were last using—even if you were using the defaults. Any time a change in size class is applied, applicationDidBecomeActive: gets called.
When app launches first time
it calls sequentially,
didFinishLaunchingWithOptions
applicationDidBecomeActive (Twice)
When we open the Control Center it calls only,
applicationDidBecomeActive
When app come from background to foreground it calls sequentially
applicationWillEnterForeground
applicationDidBecomeActive
I'm currently seeing double notifications.
It's happening because my AppDelegate's init code is being called twice.
It's being called once when the main() does [[NSBundle mainBundle] loadNibNamed:#"MainMenu" owner:application topLevelObjects:&tl] (ie, when the .XIB file is loaded), becaues the .XIB file is setting up FirstResponder to my custom AppDelegate, and then it's being called again when main() calls [[myAppDelegate alloc] init].
The init code is what does the addObserver calls, so two observers are being set up for each notification I care about, which is why my notifications get called twice.
I'm a newbie OS X programmer, so I'm not yet sure of the best way to resolve these two, but wanted to post it here in case it's of help to others, another place to look.
Have you possibly created an instance of your class in Interface Builder AND in your AppDelegate code, perhaps?
If you have code you want called only once when the app starts up, then use
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
instead.
Otherwise, applicationDidBecomeActive will be called whenever your app becomes active again, so that doesn't just mean twice as in your case, but every time the user switches back to your app after switching to another.
If you use RxSwift, then you can just throttle the application event, so it doesn't call twice in the same second:
NotificationCenter.default.rx.notification(Notification.Name.UIApplicationDidBecomeActive)
.throttle(1, scheduler: MainScheduler.instance)
.subscribe { (event) in
self.appEnteredFromBackground()
}.disposed(by: disposeBag)
private func appEnteredFromBackground() {
Analytics.trackPageView(withScreen: .home)
dataStore.checkIfAllowingRides()
}
I put this code in my actual view controller where the logic is supposed to happen on ApplicationDidBecomeActive.
I just check at top of applicationDidBecomeActive: if the request was really sent (I made a function for this, checking status), if so I return already.
The second time in applicationDidBecomeActive:, the function reads the status as Deny or Allowed, because this is after the User answered the Alert.
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:
I'm trying to get my views to update when the user returns to the app while it is running in the background. My problem is this, I call the method that updates the view and a couple of UILabels but they dont update. The strange thing is, is that I have an NSLog in the method to ensure it is being fired. So I load the app, I hit the home button to return to the home screen, I open the app, I DO get an Log reading that the method I need fired IS indeed fired but the view sint updated. Help. Please.
Use applicationDidBecomeActive for this purpose.
Template implementation has the following comment:
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
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.
I can't find any documentation to confirm this, but it appears that you can only call the method stringByEvaluatingJavaScriptFromString in overridden methods from a UIWebView delegate. Can anyone confirm this?
Here's what I've tried. I setup a button on a view, link it to a method on my viewcontroller, and make sure it works fine. My view has a UIWebView control on it as well. If I run the project on the simulator or on the iPhone, there are no issues. Then I add this code to the button's method.
[theWebView stringByEvaluatingJavaScriptFromString:#"alert('Hi there!');"];
When I run the project, I can click the button and see the 'Hi there' prompt and I can click OK to dismiss it. Usually 4-5 seconds later the simulator crashes. I occasionally see the "__TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION__" error, but not consistently; sometimes there's no error. It also doesn't always crash the first time. Sometimes I go to another page, and then try it again, and it crashes.
If I put the same code in the webPageDidFinishLoad event it works fine. But I'd like the code to be called when the user demands it so that event doesn't suit my needs.
I'm open to a workaround if you have any ideas? Thanks in advance!
I still don't know the exact reason this didn't work, but I found I could rewrite my code to get called during the UIWebView delegate methods instead.