Gestione applicationDidBecomeActive - "Come può un controller di visualizzazione rispondere all'app quando diventa attiva?"


179

Ho il UIApplicationDelegateprotocollo nella mia classe AppDelegate.m principale, con il applicationDidBecomeActivemetodo definito.

Voglio chiamare un metodo quando l'applicazione ritorna dallo sfondo, ma il metodo si trova in un altro controller di visualizzazione. Come posso verificare quale controller di visualizzazione è attualmente visualizzato nel applicationDidBecomeActivemetodo e quindi effettuare una chiamata a un metodo all'interno di quel controller?

Risposte:


304

Qualsiasi classe nella tua applicazione può diventare un "osservatore" per diverse notifiche nell'applicazione. Quando crei (o carichi) il tuo controller di visualizzazione, ti consigliamo di registrarlo come osservatore per UIApplicationDidBecomeActiveNotificatione specificare quale metodo desideri chiamare quando la notifica viene inviata alla tua applicazione.

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

Non dimenticare di ripulire dopo te stesso! Ricordati di rimuoverti come osservatore quando la tua vista sta andando via:

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

Ulteriori informazioni sul Centro notifiche .


Eccellente. Non ho pensato di usare NSNotificationCenter. Grazie!
Calvin,

3
Solo un errore di battitura in quella riga di codice (manca 'nome'): [[NSNotificationCenter defaultCenter] addObserver: auto-selettore: @selector (someMethod :) nome: UIApplicationDidBecomeActiveNotification object: nil];
Giovanni il

3
Per aggiungere alla risposta di Reed, il metodo chiamato (in questo esempio è someMethod) deve accettare un parametro NSNotification. Quindi la firma del metodo per someMethod sarebbe - (void) someMethod: (NSNotification *) notification {// Do Something Here}
Aaron

2
@Aaron Può, ma non è un requisito. Questa è una grande intuizione, però. Grazie!
Reed Olsen,

Fantastico! Che bel modo di invalidare / ricreare le istanze di NSTimer si sta facendo, proprio nella vista controller / altri oggetti che sono responsabili di quegli NSTimer. Lo adoro!
idStar,

68

Swift 3, 4 equivalente:

aggiungendo osservatore

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

rimozione dell'osservatore

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

richiama

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

2
dove lo chiamo?

1
@ user8169082, aggiungi un osservatore ovunque sia necessario iniziare a ricevere le notifiche. Puoi aggiungerlo su viewDidLoado viewWillAppear:animatedper esempio. E puoi rimuovere un osservatore quando non hai più bisogno di notifiche o quando la tua istanza di osservatore verrà deallocata nel metodo deinit
igrek,

2
rapido 4.2 Sto usando: NotificationCenter.default.addObserver (sé, selettore: #selector (applicationDidBecomeActive (notifica :)), nome: UIApplication.didBecomeActiveNotification, oggetto: nil)
Brian

16

Swift 2 equivalente :

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

Il miglior posto dove inserire removeObserverSwift: deinitmetodo.
Enrico Susatyo,

In generale, non è consigliabile accedere a sé in maniera corretta; a questo punto, il sé è tra l'essere completamente allocato e il deallocato
Zorayr,

1
Dove rimuoveresti quindi Observer?
Enrico Susatyo,

2
@EnricoSusatyo puoi ignorarlo, poiché non è corretto. Sostituire deinit va bene: "Poiché un'istanza non viene deallocata fino a quando non viene chiamato il suo deinizializzatore, un deinizializzatore può accedere a tutte le proprietà dell'istanza su cui viene chiamato e può modificare il suo comportamento in base a tali proprietà (come cercare il nome di un file che deve essere chiuso). " Chiamare deinit non è ok
Dan Rosenstark,

7

Rapido 4.2

Aggiungi osservatore

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

Rimuovi osservatore

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

Gestisci evento

@objc func handleEvent() {
}

5

Con Swift 4, Apple avvisa tramite un nuovo avviso del compilatore che ne evitiamo l'utilizzo #selectorin questo scenario. Di seguito è riportato un modo molto più sicuro per ottenere questo risultato:

Innanzitutto, crea un var pigro che può essere utilizzato dalla notifica:

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

Se desideri includere la notifica effettiva, sostituisci semplicemente _con notification.

Successivamente, impostiamo la notifica per osservare che l'app diventa attiva.

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

Il grande cambiamento qui è che invece di chiamare a #selector, ora chiamiamo il var creato sopra. Ciò può eliminare situazioni in cui si verificano arresti anomali del selettore non validi.

Infine, rimuoviamo l'osservatore.

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

1
#selectorpuò chiamare un metodo dichiarato come @objcattributo in Swift 4.
AnBisw

1
non è corretto da usare removeObserver(selfperché self non è stato assegnato durante l'aggiunta dell'osservatore. Dovresti let observer = NotificationCenter.default.addObserverquindiremoveObserver(observer
Yan Kalbaska il

Grazie @CodeBender non sapevo ancora quella funzione e (finalmente) rimuove il @objc. Tuttavia quando lo provo ricevo un avviso nella console (Xcode 11.3.1 (11C504), Swift 13.3): impossibile terminare BackgroundTask: non esiste alcuna attività in background con identificatore. Anche se salvo l'osservatore in una variabile come NSObjectProtocol.
palme

Non importa, ricevo anche l'avviso se utilizzo la @objcvariante.
palme

3

Swift 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

Il modo combinato:

import Combine

var cancellables = Set<AnyCancellable>()
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
    .sink { notification in
            // do stuff
    }.store(in: &cancellables)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.