it-swarm.com.ru

ViewDidAppear не вызывается при открытии приложения из фона

У меня есть View Controller, в котором мое значение равно 0 (метка), и когда я открываю этот View Controller от другого ViewController, я установил viewDidAppear, чтобы установить значение 20 для метки. Это работает нормально, но когда я закрываю свое приложение и затем снова открываю свое приложение, но значение не меняется, потому что viewDidLoad, viewDidAppear и viewWillAppear ничего не вызывается. Как я могу позвонить, когда я открою свое приложение. Должен ли я сделать что-нибудь из applicationDidBecomeActive?

162
Zohaib

Заинтересовавшись точной последовательностью событий, я проинструктировал приложение следующим образом: (@Zohaib, вы можете использовать приведенный ниже код NSNotificationCenter, чтобы ответить на ваш вопрос).

// AppDelegate.m

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    NSLog(@"app will enter foreground");
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    NSLog(@"app did become active");
}

// ViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"view did load");

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}

- (void)appDidBecomeActive:(NSNotification *)notification {
    NSLog(@"did become active notification");
}

- (void)appWillEnterForeground:(NSNotification *)notification {
    NSLog(@"will enter foreground notification");
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"view will appear");
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"view did appear");
}

При запуске вывод выглядит так:

2013-04-07 09:31:06.505 myapp[15459:11303] view did load
2013-04-07 09:31:06.507 myapp[15459:11303] view will appear
2013-04-07 09:31:06.511 myapp[15459:11303] app did become active
2013-04-07 09:31:06.512 myapp[15459:11303] did become active notification
2013-04-07 09:31:06.517 myapp[15459:11303] view did appear

Введите фон, затем снова введите передний план:

2013-04-07 09:32:05.923 myapp[15459:11303] app will enter foreground
2013-04-07 09:32:05.924 myapp[15459:11303] will enter foreground notification
2013-04-07 09:32:05.925 myapp[15459:11303] app did become active
2013-04-07 09:32:05.926 myapp[15459:11303] did become active notification
298
danh

Используя Objective-C

Вы должны зарегистрировать UIApplicationWillEnterForegroundNotification в вашем ViewController's viewDidLoad методе, и всякий раз, когда приложение возвращается из фона, вы можете делать все, что захотите, в методе, зарегистрированном для уведомления. ViewController's viewWillAppear или viewDidAppear не будет вызываться при возврате приложения из фона на передний план.

-(void)viewDidLoad{

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doYourStuff)

  name:UIApplicationWillEnterForegroundNotification object:nil];
}

-(void)doYourStuff{

   // do whatever you want to do when app comes back from background.
}

Не забудьте отменить регистрацию уведомления, на которое вы зарегистрированы.

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Примечание если вы зарегистрируете viewController для UIApplicationDidBecomeActiveNotification, тогда ваш метод будет вызываться каждый раз, когда ваше приложение станет активным. Не рекомендуется регистрировать viewController для этого уведомления.

Используя Swift

Для добавления наблюдателя вы можете использовать следующий код

 override func viewDidLoad() {
    super.viewDidLoad()

     NSNotificationCenter.defaultCenter().addObserver(self, selector:"doYourStuff", name:
     UIApplicationWillEnterForegroundNotification, object: nil)
 }

 func doYourStuff(){
     // your code
 }

Для удаления наблюдателя вы можете использовать функцию deinit Swift.

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}
126
nsgulliver

Версия Swift 3.0 ++

В вашем viewDidLoad зарегистрируйтесь в центре уведомлений, чтобы прослушать это открытое из фонового действия

NotificationCenter.default.addObserver(self, selector:#selector(doSomething), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)

Затем добавьте эту функцию и выполните необходимые действия

func doSomething(){
    //...
}

Наконец добавьте эту функцию, чтобы очистить наблюдателя уведомлений, когда ваш контроллер представления разрушен.

deinit {
    NotificationCenter.default.removeObserver(self)
}
39
Fangming

Я думаю, что регистрация для UIApplicationWillEnterForegroundNotification опасна, так как вы можете получить более одного контроллера, реагирующего на это уведомление. Ничто не гарантирует, что эти контроллеры все еще видны при получении уведомления.

Вот что я делаю: я принудительно вызываю viewDidAppear на активном контроллере прямо из делегата приложения методом didBecomeActive:

Добавьте приведенный ниже код в - (void)applicationDidBecomeActive:(UIApplication *)application

UIViewController *activeController = window.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
    activeController = [(UINavigationController*)window.rootViewController topViewController];
}
[activeController viewDidAppear:NO];
4
Erwan

Свифт 4.2. версия

Зарегистрируйтесь в NotificationCenter в viewDidLoad, чтобы получать уведомления, когда приложение возвращается из фона

NotificationCenter.default.addObserver(self, selector: #selector(doSomething), name: UIApplication.willEnterForegroundNotification, object: nil)

Реализуйте метод, который должен быть вызван.

@objc private func doSomething() {
    // Do whatever you want, for example update your view.
}

Вы можете удалить наблюдателя после уничтожения ViewController. Это требуется только ниже iOS9 и MacOS 10.11

deinit {
    NotificationCenter.default.removeObserver(self)
}
4
gebirgsbärbel

Просто зарегистрируйте контроллер представления для уведомления UIApplicationWillEnterForegroundNotification и отреагируйте соответствующим образом.

3
andreagiavatto

попробуйте добавить это в AppDelegate applicationWillEnterForeground.

func applicationWillEnterForeground(_ application: UIApplication) {        
    // makes viewWillAppear run
    self.window?.rootViewController?.beginAppearanceTransition(true, animated: false)
    self.window?.rootViewController?.endAppearanceTransition()
}
2
richc

Согласно документации Apple:

(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated;

Описание:
Сообщает дочернему контроллеру, что его внешний вид скоро изменится. Если вы реализуете пользовательский контроллер контейнера, используйте этот метод, чтобы сообщить дочернему элементу, что его представления собираются появиться или исчезнуть. Не вызывайте viewWillAppear:, viewWillDisappear:, viewDidAppear: или viewDidDisappear: напрямую.

(void)endAppearanceTransition;

Описание:

Сообщает дочернему контроллеру, что его внешний вид изменился. Если вы реализуете пользовательский контроллер контейнера, используйте этот метод, чтобы сообщить дочернему элементу, что переход представления завершен.

Пример кода:

(void)applicationDidEnterBackground:(UIApplication *)application
{

    [self.window.rootViewController beginAppearanceTransition: NO animated: NO];  // I commented this line

    [self.window.rootViewController endAppearanceTransition]; // I commented this line

}

Вопрос: Как я исправил?

Ответ: Я нашел этот кусок строк в приложении. Эти строки заставили мое приложение не получать никаких уведомлений ViewWillAppear. Когда я прокомментировал эти строки, все работает нормально.

1
Lakshmi