почему мое приложение для iOS перезапускается с первого экрана после возврата в режим переднего плана?

Когда в приложении My iOS, которое находится на экране сведений, я нажимаю кнопку «Домой», что приводит к переходу в фоновый режим. После бездействия около 7 минут я перезапускаю его, и он не запускается с того места, где я его оставил. Начинается с первого экрана.

Я попал в Интернет и узнал о государственной консервации и реставрации. Я реализовал на одном экране, но, похоже, он не работает. Это то, что я сделал в appDelegate.m

    //appDelegate.m

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

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

Следующий код находится в appDelegate.m в методе willFinishLaunchingWithOptions. Я не использую раскадровку, так как это приложение очень старое. У него есть XIB. Таким образом, этому приложению всегда нужно переходить на экран входа в систему, где проверяется, сохранен ли accessToken, он переходит на главный экран с экрана входа в систему. Если не сохранить, он останется на экране входа в систему. Так что это обязательно для выполнения. Таким образом, есть только один способ закодировать это, как показано ниже.

- (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;
   ...
   ...
}

Я дал restoreId всем контроллерам представления, как показано ниже, в viewDidLoad(). Например, это то, что я сделал в 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];
    }

Теперь, когда я перехожу на экран PetDetail и нажимаю кнопку «Домой», вызывается encodeRestorableStateWithCoder(). Остановка приложения из xcode, перезапуск его остается на том же экране, но сразу же переходит на экран входа в систему и переходит на главный экран (может выполняться код в willFinishLaunchingWithOptions)

Я делаю что-то не так? Как предотвратить перезапуск приложения с первого экрана, если пользователь не убьет его вручную?


person Hiren Prajapati    schedule 11.10.2017    source источник
comment
Посмотрите, не написали ли вы что-нибудь для сброса в методах viewWillEnterForeground или didBecomeActive. Кроме того, вы можете проверить объем памяти вашего приложения. Ваше приложение может быть убито системой по какой-то причине.   -  person Puneet Sharma    schedule 11.10.2017
comment
@PuneetSharma спасибо. На самом деле это сбрасывало настройки, когда приложение становилось активным. Есть ли способ отследить, почему система убивает мое приложение в фоновом режиме через несколько минут?   -  person Hiren Prajapati    schedule 11.10.2017
comment
@HirenPrajapati каждое приложение уничтожается, если оно находится в фоновом режиме более 3 минут, а ОС требуется больше памяти для других приложений.   -  person Varun Naharia    schedule 11.10.2017
comment
@HirenPrajapati: Поскольку вы сбрасывали вещи в didBecomeActive, который вызывается каждый раз, когда вы перемещаете приложение на передний план, как вы говорите, что приложение убивается в приостановленном состоянии?   -  person Puneet Sharma    schedule 11.10.2017
comment
@PuneetSharma все говорят, что iOS приостанавливает работу приложения через несколько минут после того, как оно переходит в фоновый режим.   -  person Hiren Prajapati    schedule 11.10.2017
comment
@HirenPrajapati: Да, это так, но приложение приостановлено, т. Е. Никакой код не выполняется, но оно еще не завершено. Если нет требований (возникающих из-за нехватки памяти), приложение не будет остановлено и может быть возобновлено из приостановленного состояния.   -  person Puneet Sharma    schedule 11.10.2017
comment
@HirenPrajapati, не могли бы вы опубликовать код, написанный в методе didBecomeActive?   -  person Varun Naharia    schedule 11.10.2017
comment
@VarunNaharia Вызывается ли метод didFinishLaunchingWithOptions, когда происходит восстановление? Я инициализировал UIViewController в качестве контроллера корневого представления в методе didFinishLaunchingWithOptions. Как вы думаете, это то, что заставляет приложение перезапускаться с первого экрана?   -  person Hiren Prajapati    schedule 12.10.2017
comment
@PuneetSharma Вызывается ли метод didFinishLaunchingWithOptions, когда происходит восстановление? Я инициализировал UIViewController в качестве контроллера корневого представления в методе didFinishLaunchingWithOptions. Как вы думаете, это то, что заставляет приложение перезапускаться с первого экрана?   -  person Hiren Prajapati    schedule 12.10.2017
comment
@HirenPrajapati: Нет, он не вызывается, когда приложение выходит из приостановленного состояния. willEnterForeground и didBecomeActive вызываются. Вы все еще сталкиваетесь с проблемой с вашим кодом? Вы упомянули, что сбрасывали настройки в didBecomeActive.   -  person Puneet Sharma    schedule 12.10.2017
comment
@PuneetSharma Я действительно проверил, и код в didBecomeActive был просто для вызова API и использования ответа для обновления базы данных. Я не видел никакой инициализации экрана в этом методе. И даже я пытался прокомментировать этот код и до сих пор не смог решить эту проблему.   -  person Hiren Prajapati    schedule 12.10.2017
comment
Трудно сказать, что происходит не так, не видя вашего кода. Можете ли вы загрузить код на github или еще куда-нибудь. Я могу взглянуть на это. Кроме того, выполняете ли вы какие-либо фоновые задачи с помощью backgroundTaskWithExpirationHandler?   -  person Puneet Sharma    schedule 12.10.2017
comment
@HirenPrajapati, если вы хотите исправить, сохраните список UINavigationController.viewControllers, сохраненный по умолчанию для пользователя, и прочитайте его, и On UINavigationController.viewController = {viewController from UserDefaults}, если это не работает или у вас есть какие-либо недоразумения, сообщите об этом   -  person Varun Naharia    schedule 12.10.2017
comment
@PuneetSharma Хорошо, я узнал, что деталь в ViewController, на которой я тестирую, encodeRestorableStateWithCoder и decodeRestorableStateWithCoder никогда не вызываются. Это старый проект, поэтому он использует xib, но все делается программно. Контроллер навигации создается в appDelegate программно, и все экраны перемещаются с помощью метода initWithNibName. Я даже написал следующее во ViewDidLoad тестового класса: self.navigationController.restorationIdentifier = @MatchedPetIdentificationNavigation; self.restorationIdentifier = @MatchedPetIdentification;   -  person Hiren Prajapati    schedule 12.10.2017
comment
@VarunNahariaOkay, я узнал, что деталь в ViewController, на которой я тестирую, encodeRestorableStateWithCoder и decodeRestorableStateWithCoder никогда не вызываются. Это старый проект, поэтому он использует xib, но все делается программно. Я даже написал в ViewDidLoad этого класса следующее: self.navigationController.restorationIdentifier = @MatchedPetIdentificationNavigation; self.restorationIdentifier = @MatchedPetIdentification; self.restorationClass = [сам класс]   -  person Hiren Prajapati    schedule 12.10.2017
comment
@HirenPrajapati Я создал рабочий пример, пожалуйста, проверьте мой ответ   -  person Varun Naharia    schedule 12.10.2017
comment
@VarunNaharia спасибо за пример. Это не решит мою проблему. Нужно ли вызывать методы willEncodeRestorableStateWithCoder и didDecodeRestorableStateWithCoder? Я использовал XIB, может быть, поэтому я застрял здесь.   -  person Hiren Prajapati    schedule 12.10.2017
comment
@VarunNaharia это в willFinishLaunchingWithOptions(): homeViewController = [[HomeViewController alloc] initWithNibName:@HomeViewController bundle:nil]; self.navigationController = [[UINavigationController alloc]initWithRootViewController:homeViewController]; self.navigationController.restorationIdentifier = @NavigationController; self.window.rootViewController = self.navigationController; Это приводит к перезапуску приложения. Пожалуйста, вы можете решить это?   -  person Hiren Prajapati    schedule 12.10.2017
comment
@HirenPrajapati, когда я попробовал пример приложения, он дает мне последний открытый UIViewController даже после закрытия приложения из фона. Как это не работает для вас, есть что-то, что вы не можете здесь объяснить, поэтому это занимает так много времени, чтобы решить ваша проблема, пожалуйста, добавьте больше информации изображения (gif)   -  person Varun Naharia    schedule 12.10.2017
comment
@HirenPrajapati, пожалуйста, добавьте код в вопросе, который трудно прочитать в комментарии, да, ваша проблема может быть решена, просто нужно время, чтобы правильно понять вашу проблему.   -  person Varun Naharia    schedule 12.10.2017
comment
@VarunNaharia Привет, я только что отредактировал свой вопрос. Пожалуйста, пройдите через это. Думаю, это заставит вас понять, что происходит. Воспроизвести как можно скорее   -  person Hiren Prajapati    schedule 12.10.2017
comment
@VarunNaharia Я обязательно инициализирую loginviewcontroller как корневой контроллер представления. В классе loginviewcontroller я проверяю, вошел ли пользователь в систему или нет. Это объясняется в отредактированном вопросе.   -  person Hiren Prajapati    schedule 12.10.2017
comment
@HirenPrajapati, так что вам нужно открыть экран входа в систему, если пользователь не вошел в систему, и открыть главный экран, если пользователь вошел в систему? Поправьте меня, если я неправильно понимаю   -  person Varun Naharia    schedule 12.10.2017
comment
@VarunNaharia, независимо от того, вошел ли пользователь в систему или нет, приложение обязательно должно перейти на экран входа в систему. В viewWillAppear() экрана входа в систему я проверяю, сохранен ли уже токен входа, приложение само перейдет на главный экран. Для получения дополнительной информации проверьте отредактированный вопрос, если вы еще этого не сделали.   -  person Hiren Prajapati    schedule 12.10.2017
comment
@HirenPrajapati, вы делаете это неправильно, так как весь ваш код не нужен, если ваш пользователь уже вошел в систему, тогда зачем показывать ему экран входа в систему, вы можете просто проверить статус входа пользователя за кулисами и решить с помощью контроллера, чтобы показать   -  person Varun Naharia    schedule 12.10.2017
comment
@VarunNaharia Это старое приложение. У меня нет прав на изменение его старого функционала вместо добавления нового. И я думаю, что это не проблема, которая вызывает мою текущую проблему. Короче говоря, LoginViewController — это домашний экран. После выхода из приложения на подробном экране перезапустите приложение, оно должно остаться на подробном экране (в данном случае: PetDetailViewController). Но он всегда идет на первый экран. Надеюсь, теперь вы полностью понимаете мою проблему.   -  person Hiren Prajapati    schedule 12.10.2017
comment
@HirenPrajapati, пожалуйста, проверьте обновленный ответ   -  person Varun Naharia    schedule 12.10.2017
comment
@VarunNaharia, ты совершенно неправильно понял. Это не касается входа в систему. Возьмите loginviewcontroller в качестве домашнего экрана. В willFinishLaunchingWithOptions() я инициализирую домашний экран. Я предполагаю, что это единственный способ в проекте Xib, которым вы можете инициализировать любой контроллер просмотра в качестве начального контроллера просмотра. Моя проблема заключается в том, что когда приложение переходит в фоновый режим, когда оно находится на подробном экране, через несколько минут после перезапуска оно запускается с домашнего экрана. Я хочу перезапустить приложение с подробным экраном. Так что речь идет о государственной консервации и реставрации. Поэтому я реализовал это. Но он все еще вызывает домашний экран. Проверьте отредактированный вопрос, пожалуйста.   -  person Hiren Prajapati    schedule 12.10.2017


Ответы (1)


Вы не можете контролировать, когда ваше приложение переходит в состояние приостановки из фонового состояния, ОС автоматически сделает это, чтобы выделить больше памяти для приложений переднего плана. Для получения дополнительной информации о переходах между состояниями и завершении работы приложения вы можете обратиться к:

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

person Mike Atkins-Spelling    schedule 11.10.2017
comment
предоставленная вами ссылка просто показывает документацию UIKit developer.apple.com/documentation/uikit/ app_and_environment/ - person Pavel Bogart; 19.10.2020