Поводження з програмоюDidBecomeActive - "Як контролер перегляду може реагувати на додаток, що стає активним?"


179

У мене UIApplicationDelegateв основному класі AppDelegate.m протокол із applicationDidBecomeActiveвизначеним методом.

Я хочу викликати метод, коли програма повертається з фону, але метод знаходиться в іншому контролері перегляду. Як я можу перевірити, який в даний час показник відображається в applicationDidBecomeActiveметоді, а потім здійснити виклик методу в цьому контролері?

Відповіді:


304

Будь-який клас у вашій програмі може стати «спостерігачем» за різними сповіщеннями у програмі. Коли ви створюєте (або завантажуєте) свій контролер перегляду, ви захочете зареєструвати його як спостерігача UIApplicationDidBecomeActiveNotificationта вказати, який метод ви хочете зателефонувати, коли це повідомлення надійде у вашу заявку.

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(someMethod:)
                                             name:UIApplicationDidBecomeActiveNotification object:nil];

Не забувайте прибирати за собою! Не забудьте видалити себе в якості спостерігача, коли ваш погляд згасає:

[[NSNotificationCenter defaultCenter] removeObserver:self 
                                                name:UIApplicationDidBecomeActiveNotification
                                              object:nil];

Більше інформації про Центр сповіщень .


Відмінно. Не думав використовувати NSNotificationCenter. Дякую!
Кальвін

3
Просто помилка в цьому рядку коду (відсутнє 'ім'я'): [[NSNotificationCenter defaultCenter] addObserver: self select: @selector (someMethod :) ім'я: UIApplicationDidBecomeActiveNotification object: nil];
Іоаннус

3
Щоб додати відповідь Ріда, метод, який викликається (у цьому прикладі це деякий метод), повинен прийняти параметр NSNotification. Тож підписом методу для someMethod було б - (недійсне) someMethod: (NSNotification *) сповіщення {// Зроби щось тут}
Aaron

2
@Aaron Це може, але це не є вимогою. Але це чудове розуміння. Дякую!
Рід Олсен

Фантастичний! Який чудовий спосіб визнати недійсним / відтворити екземпляри NSTimer, які ви хочете, прямо у контролерах перегляду / інших об'єктах, які відповідають за ці NSTimers. Любіть це!
idStar

68

Швидкий 3, 4 еквівалент:

додавання спостерігача

NotificationCenter.default.addObserver(self,
    selector: #selector(applicationDidBecomeActive),
    name: .UIApplicationDidBecomeActive, // UIApplication.didBecomeActiveNotification for swift 4.2+
    object: nil)

усунення спостерігача

NotificationCenter.default.removeObserver(self,
    name: .UIApplicationDidBecomeActive, // UIApplication.didBecomeActiveNotification for swift 4.2+
    object: nil)

зворотний дзвінок

@objc func applicationDidBecomeActive() {
    // handle event
}

2
куди я це називаю?

1
@ user8169082, ви додаєте спостерігача там, де потрібно, щоб почати отримувати сповіщення. Ви можете додати його viewDidLoadабо, viewWillAppear:animatedнаприклад. І ви можете видалити спостерігач , коли ви більше неповідомлення необхідності, або коли екземпляр спостерігача збираєтеся бути вивільнені в методі Deinit
ігрек

2
swift 4.2 Я використовую: NotificationCenter.default.addObserver (власний, вибір: #selector (applicationDidBecomeActive (повідомлення :)), ім'я: UIApplication.didBecomeActiveNotification, об’єкт: nil)
Brian

16

Швидкий 2 Еквівалент :

let notificationCenter = NSNotificationCenter.defaultCenter()

// Add observer:
notificationCenter.addObserver(self,
  selector:Selector("applicationWillResignActiveNotification"),
  name:UIApplicationWillResignActiveNotification,
  object:nil)

// Remove observer:
notificationCenter.removeObserver(self,
  name:UIApplicationWillResignActiveNotification,
  object:nil)

// Remove all observer for all notifications:
notificationCenter.removeObserver(self)

// Callback:
func applicationWillResignActiveNotification() {
  // Handle application will resign notification event.
}

Найкраще місце для removeObserverSwift: deinitметод.
Енріко Сусатьо

Взагалі, доступ до себе в deinit не рекомендується; на даний момент я перебуваю між тим, що буде повністю розподілений та розподілений
Зорайр

1
Звідки ви тоді видалите Observer?
Енріко Сусатьо

2
@EnricoSusatyo ви можете проігнорувати це, оскільки це неправильно. Переважна деінітація є прекрасною: "Оскільки екземпляр не розміщений до того моменту, як викликається його деінціалізатор, дезініціалізатор може отримати доступ до всіх властивостей екземпляра, на який він викликаний, і може змінити свою поведінку на основі цих властивостей (наприклад, пошук імені файл, який потрібно закрити). " Викликати deinit не в порядку
Dan Rosenstark

7

Швидкий 4.2

Додати спостерігача-

NotificationCenter.default.addObserver(self, selector: #selector(handleEvent), name: UIApplication.didBecomeActiveNotification, object: nil)

Видалити спостерігача-

NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)

Обробляти події-

@objc func handleEvent() {
}

5

Завдяки Swift 4, Apple радить через нове попередження компілятора, щоб ми уникали використання #selectorцього сценарію. Нижче подано набагато безпечніший спосіб досягти цього:

Спочатку створіть лінивий var, який може бути використаний сповіщенням:

lazy var didBecomeActive: (Notification) -> Void = { [weak self] _ in
    // Do stuff
} 

Якщо вам потрібно фактичне повідомлення буде включено, просто замінити _з notification.

Далі ми налаштовуємо сповіщення, щоб спостерігати за тим, як додаток стає активним.

func setupObserver() {
    _ = NotificationCenter.default.addObserver(forName: .UIApplicationDidBecomeActive,
                                               object: nil,
                                               queue:.main,
                                               using: didBecomeActive)
}

Велика зміна тут полягає в тому, що замість виклику a #selectorми тепер називаємо var, створений вище. Це може усунути ситуації, коли ви отримуєте недійсні збої селектора.

Нарешті, ми видаляємо спостерігача.

func removeObserver() {
    NotificationCenter.default.removeObserver(self, name: .UIApplicationDidBecomeActive, object: nil)
}

1
#selectorможна викликати метод, оголошений як @objcатрибут у Swift 4.
AnBisw

1
його неправильно використовувати, removeObserver(selfоскільки self не було призначено при додаванні спостерігача. let observer = NotificationCenter.default.addObserverТоді вам слідremoveObserver(observer
Ян Калбаска,

Спасибі @CodeBender Я ще не знав цієї функції, і вона (нарешті) видаляє @objc. Однак, коли я спробую це, я отримую попередження на консолі (Xcode 11.3.1 (11C504), Swift 13.3): Не вдається закінчити BackgroundTask: не існує фонового завдання з ідентифікатором. Навіть якщо я збережу спостерігача в змінній як NSObjectProtocol.
пальма

Я також отримую попередження, якщо використовую @objcваріант.
пальма

3

Швидкий 5

fileprivate  func addObservers() {
      NotificationCenter.default.addObserver(self,
                                             selector: #selector(applicationDidBecomeActive),
                                             name: UIApplication.didBecomeActiveNotification,
                                             object: nil)
    }

fileprivate  func removeObservers() {
        NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
    }

@objc fileprivate func applicationDidBecomeActive() {
// here do your work
    }

0

Спосіб комбінування:

import Combine

var cancellables = Set<AnyCancellable>()
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
    .sink { notification in
            // do stuff
    }.store(in: &cancellables)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.