why my iOS app restarts from first screen after coming back to foreground mode?
Asked Answered
S

1

7

When in My iOS app which which is in the detail screen and I press home button which will result it in going to background mode. After inactivity of 7 around minutes, I relaunch it and it doesn't start from where I left it. It starts from the first screen.

I hit the internet and came to know about state preservation and restoration. I implemented in one screen but it doesn't seem to work. This is what I did in appDelegate.m

    //appDelegate.m

    -(BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
    {
        return YES;
    }

    -(BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
    {
        return YES;
    }

Following code is in appDelegate.m in willFinishLaunchingWithOptions method. I am not using storyboard as this app is very old. It has XIBs. So this app always needs to go to login screen where it is checked if accessToken is stored, it will go to home screen from login screen. If not stored, it will remain in login screen. So this is mandatory to perform. Thus there is only one way to code this like below.

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
   ...
   ...
   loginViewController = [[LoginViewController alloc] initWithNibName:@"LoginViewController" bundle:nil];

   self.navigationController = [[UINavigationController alloc]initWithRootViewController:loginViewController];
   self.navigationController.restorationIdentifier = @"NavigationController";
   [loginViewController.view setBackgroundColor:[UIColor whiteColor]];
   self.window.rootViewController = self.navigationController;
   ...
   ...
}

I have given restorationId to all view controller like below in viewDidLoad(). For example This is what I did in PetDetailViewController.m

    - (void)viewDidLoad
    {
        [super viewDidLoad];

        self.restorationIdentifier = @"MatchedPetIdentification";
        self.restorationClass = [self class];
    }

    -(void)encodeRestorableStateWithCoder:(NSCoder *)coder
    {
        [super encodeRestorableStateWithCoder:coder];
    }

    -(void)decodeRestorableStateWithCoder:(NSCoder *)coder
    {
        [super decodeRestorableStateWithCoder:coder];
    }

Now when I go to PetDetail screen and press home button, encodeRestorableStateWithCoder() gets called. Stopping app from xcode, relaunching it stays on same screen but immediately goes to login screen and transit to home screen(code in willFinishLaunchingWithOptions might be executing)

Am I doing anything wrong? How to prevent app from restarting from first screen unless user kills it manually?

Subarid answered 11/10, 2017 at 8:31 Comment(28)
Look at whether you have written anything to reset in viewWillEnterForeground or didBecomeActive methods. Also, you may want to check memory footprint of your app. Your app may be getting killed by System for some reason.Combined
@PuneetSharma thanks. It actually was resetting things when app becomes active. Is there any way I can track down why system is killing my app in background after few minutes?Subarid
@HirenPrajapati every app is killed if it's in background mode for more then 3 min and OS needs more memory for other apps.Pleinair
@HirenPrajapati: Because you were resetting things in didBecomeActive, that gets called everytime ypu move app to foregorund, how do you say that the app is getting killed in suspended state?Combined
@PuneetSharma everyone is saying that iOS suspends the app few minutes after the app goes in background.Subarid
@HirenPrajapati: Yes it does, but the app is suspended, i.e, not running any code but it is not yet terminated. If there is no requirement(that arises because of memory crunch), the app will no be terminated and can be resumed from suspended state.Combined
@HirenPrajapati will you please post the code that is written in didBecomeActive method ?Pleinair
@VarunNaharia Is 'didFinishLaunchingWithOptions' method called when restoration takes place? I have initialised a UIViewController as a root view controller in didFinishLaunchingWithOptions method. Do you think this is what forces the app to restart from first screen?Subarid
@PuneetSharma Is 'didFinishLaunchingWithOptions' method called when restoration takes place? I have initialised a UIViewController as a root view controller in didFinishLaunchingWithOptions method. Do you think this is what forces the app to restart from first screen?Subarid
@HirenPrajapati: No it does not get called, when app resumes from suspended state. willEnterForeground and didBecomeActive gets called. Are you still facing issue with your code? You mentioned you were resetting thing in didBecomeActiveCombined
@PuneetSharma I actually checked and the code in didBecomeActive was just to call API and use response to update database. I didn't seen any screen initialisation in this method. And even I tried to comment this code and still not able to resolve this issue.Subarid
It is difficult to say what is getting wrong without seeing your code. Can you upload the code at github or somewhere. I can take a look at it. Also, are you performing any background task using backgroundTaskWithExpirationHandler?Combined
@HirenPrajapati if you want fix save UINavigationController.viewControllers list saved in user default and read back and On UINavigationController.viewController = {viewController from UserDefaults}, If it not works or you have any confusion let know about itPleinair
@PuneetSharma Okay, I came to know that detail in ViewController I'm testing on, encodeRestorableStateWithCoder and decodeRestorableStateWithCoder never get called. This is old project so it is using xib but everything is done programatically. Navigation controller is created in appDelegate programatically and all screens are navigated using initWithNibName method. I even wrote following in ViewDidLoad of testing class: self.navigationController.restorationIdentifier = @"MatchedPetIdentificationNavigation"; self.restorationIdentifier = @"MatchedPetIdentification";Subarid
@VarunNahariaOkay, I came to know that detail in ViewController I'm testing on, encodeRestorableStateWithCoder and decodeRestorableStateWithCoder never get called. This is old project so it is using xib but everything is done programatically. I even wrote following in ViewDidLoad of this class: self.navigationController.restorationIdentifier = @"MatchedPetIdentificationNavigation"; self.restorationIdentifier = @"MatchedPetIdentification"; self.restorationClass = [self class]Subarid
@HirenPrajapati I have created a working example for please check my answerPleinair
@VarunNaharia thanks for giving example. It won't solve my problem. Do I need to call willEncodeRestorableStateWithCoder and didDecodeRestorableStateWithCoder methods? I have used XIBs, maybe thats why I'm stuck here.Subarid
@VarunNaharia this is in willFinishLaunchingWithOptions(): homeViewController = [[HomeViewController alloc] initWithNibName:@"HomeViewController" bundle:nil]; self.navigationController = [[UINavigationController alloc]initWithRootViewController:homeViewController]; self.navigationController.restorationIdentifier = @"NavigationController"; self.window.rootViewController = self.navigationController; This is causing app to restart. Please can you solve this?Subarid
@HirenPrajapati when I tried the example app it is giving me the last opened UIViewController even after terminating app from background, How it is not working for you, there is something that you are unable to explain here that's why it's taking this much time to solve your problem, please add more information images(gif)Pleinair
@HirenPrajapati please add code in question it's hard to read in comment, yes your problem can be solved it's just taking time in understating your problem correctlyPleinair
@VarunNaharia Hey, I've just edited my question. Please go through it. I guess this will make you understand what is happening. Replay ASAPSubarid
@VarunNaharia I mandatory initialise loginviewcontroller as root view controller. In loginviewcontroller class, I check if user already has logged in or not. This is explained in edited question.Subarid
@HirenPrajapati so your basic need is Open Login Screen if user not logged in and open home screen if user is logged in ? Correct me if I am understanding wrongPleinair
@VarunNaharia wether user logged in or not, it is compulsory for the app to go to loginscreen. In loginscreen's viewWillAppear(), I check if login token is already stored, app will go to home screen itself. For further info check edited question in case you haven'tSubarid
@HirenPrajapati you are doing it wrong way all your code is unnecessary if you user is already logged in then why show him login screen you can just check user login status behind the scene and decide with controller to showPleinair
@VarunNaharia This is an old app. I do not have rights to change its old functionality rather than adding new ones. And I guess this isn't an issue which is causing my current problem. In short, LoginViewController is a homescreen. After go out of app when in detail screen, relaunch the app, it should remain in detailscreen(in this case: PetDetailViewController). But it always goes to first screen. I hope you now completely understand my problem.Subarid
@HirenPrajapati please check updated answerPleinair
@VarunNaharia you completely got it wrong. This is not about login.Take loginviewcontroller as homescreen. In willFinishLaunchingWithOptions(), I initialise homescreen. I guess this is the only way in Xib project you can initialise any viewcontroller as an initial viewcontroller. My problem is when app goes in background while in detailscreen, few minutes after relaunching it starts from homescreen. I want app to relaunch with detail screen. So this is about state preservation and restoration. So I implemented this. But it still calling homescreen. Check edited question please.Subarid
G
1

You cannot control when your app is put into a suspended state from the background state, the OS will automatically do this to allow more memory for foreground apps. For more information on state transitions and app termination you can refer to:

https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html

Gook answered 11/10, 2017 at 8:43 Comment(1)
the link you provided just shows UIKit documentation developer.apple.com/documentation/uikit/app_and_environment/…Disreputable

© 2022 - 2024 — McMap. All rights reserved.