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

135

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

  • 0
    Когда приложение станет активным, вы можете опубликовать локальное уведомление и добавить свой контроллер представления в качестве наблюдателя и обновить значения.
Теги:
xcode
iphone

7 ответов

272
Лучший ответ

Интересно о точной последовательности событий, я применил приложение следующим образом: (@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
  • 1
    Дан, вы сопоставили UIApplicationWillEnterForegroundNotification с appDidEnterForeground :. Разве это не вводит в заблуждение? Обратите внимание на «будет» и «сделал». Это было намеренно?
  • 0
    @Lubiluk - не намеренно. Я отредактирую Хороший улов.
Показать ещё 3 комментария
116

Использование Objective-C

Вы должны зарегистрировать UIApplicationWillEnterForegroundNotification в своем методе ViewController viewDidLoad, и всякий раз, когда приложение возвращается с фона, вы можете делать все, что хотите, в методе, зарегистрированном для уведомления. ViewController 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 быстрого доступа.

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}
  • 5
    Имеет замечательное сходство со stackoverflow.com/a/15854893/341994 :)
  • 4
    Да, это так :) Иногда трудно найти ответы :)
Показать ещё 1 комментарий
23

Версия Swift 3.0 ++

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

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

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

func doSomething(){
    //...
}

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

deinit {
    NotificationCenter.default.removeObserver(self)
}
  • 0
    Простое и понятное решение для обработки уведомлений внутри ВК +1
  • 0
    Не могу поверить, что этот хороший ответ пропущен во многих других похожих / дублирующих SO вопросах.
4

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

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

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

UIViewController *activeController = window.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
    activeController = [(UINavigationController*)window.rootViewController topViewController];
}
[activeController viewDidAppear:NO];
  • 7
    Это гарантируется, если контроллер отменяет регистрацию (как и должно быть) для UIApplicationWillEnterForegroundNotification в viewWillDisappear, а не в dealloc. Вызов viewDidAppear явно выглядит для меня как хак, он нарушает семантику (личное представление) и может сбить людей с толку (из опыта).
2

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

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

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

  • 0
    Как я это сделаю? я вызвал мой viewController в applicationDidBecomeActive, но. это перекрывает viewController или это нормально делать?
  • 2
    Не вызывайте ваш viewController в applicationDidBecomeActive (что в любом случае неправильно, потому что он вызывается несколько раз). Зарегистрируйтесь для получения уведомления в вашем viewDidLoad как предложено @nsgulliver. Ваш viewDidAppear также вызовет doYourStuff чтобы установить для вашей метки желаемое значение.
1

Согласно документации 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

}

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню