Umgang mit applicationDidBecomeActive - "Wie kann ein View Controller darauf reagieren, dass die App aktiv wird?"

179

Ich habe das UIApplicationDelegateProtokoll in meiner Hauptklasse AppDelegate.m mit der applicationDidBecomeActivedefinierten Methode.

Ich möchte eine Methode aufrufen, wenn die Anwendung aus dem Hintergrund zurückkehrt, die Methode sich jedoch in einem anderen Ansichtscontroller befindet. Wie kann ich überprüfen, welcher View-Controller derzeit in der applicationDidBecomeActiveMethode angezeigt wird, und dann eine Methode in diesem Controller aufrufen?

Calvin
quelle

Antworten:

304

Jede Klasse in Ihrer Anwendung kann ein "Beobachter" für verschiedene Benachrichtigungen in der Anwendung werden. Wenn Sie Ihren View Controller erstellen (oder laden), möchten Sie ihn als Beobachter für die registrieren UIApplicationDidBecomeActiveNotificationund angeben, welche Methode Sie aufrufen möchten, wenn diese Benachrichtigung an Ihre Anwendung gesendet wird.

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

Vergiss nicht, nach dir selbst aufzuräumen! Denken Sie daran, sich als Beobachter zu entfernen, wenn Ihre Sicht verschwindet:

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

Weitere Informationen zum Notification Center .

Reed Olsen
quelle
Ausgezeichnet. Ich habe nicht daran gedacht, es zu benutzen NSNotificationCenter. Danke dir!
Calvin
3
Nur ein Tippfehler in dieser Codezeile (fehlender 'Name'): [[NSNotificationCenter defaultCenter] addObserver: Selbstselektor: @selector (someMethod :) Name: UIApplicationDidBecomeActiveNotification Objekt: nil];
Johnus
3
Um Reeds Antwort zu ergänzen, muss die aufgerufene Methode (in diesem Beispiel someMethod) einen NSNotification-Parameter akzeptieren. Die Methodensignatur für someMethod wäre also - (void) someMethod: (NSNotification *) Benachrichtigung {// Do Something Here}
Aaron
2
@ Aaron Es kann, aber es ist keine Voraussetzung. Das ist jedoch eine großartige Einsicht. Vielen Dank!
Reed Olsen
Fantastisch! Was für eine großartige Möglichkeit, NSTimer-Instanzen ungültig zu machen / neu zu erstellen, direkt in den View-Controllern / anderen Objekten, die für diese NSTimer verantwortlich sind. Liebe es!
idStar
68

Swift 3, 4 Äquivalent:

Beobachter hinzufügen

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

Beobachter entfernen

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

zurückrufen

@objc func applicationDidBecomeActive() {
    // handle event
}
igrek
quelle
2
wo nenne ich das
1
@ user8169082, Sie fügen einen Beobachter hinzu, wo immer Sie Benachrichtigungen erhalten möchten. Sie können es hinzufügen viewDidLoadoder viewWillAppear:animatedzum Beispiel. Und Sie können einen Beobachter entfernen, wenn Sie keine Benachrichtigungen mehr benötigen oder wenn Ihre Beobachterinstanz in der Deinit-Methode freigegeben wird
igrek
2
swift 4.2 Ich verwende: NotificationCenter.default.addObserver (self, Selektor: #selector (applicationDidBecomeActive (Benachrichtigung :)), Name: UIApplication.didBecomeActiveNotification, Objekt: nil)
Brian
16

Swift 2-Äquivalent :

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.
}
Zorayr
quelle
Bester Ort für removeObserverSwift: deinitMethode.
Enrico Susatyo
Im Allgemeinen wird davon abgeraten, in deinit auf self zuzugreifen. Zu diesem Zeitpunkt befindet sich das Selbst zwischen der vollständigen Zuweisung und der Freigabe
Zorayr
1
Wo würden Sie dann den Server entfernen?
Enrico Susatyo
2
@EnricoSusatyo können Sie das ignorieren, da es nicht korrekt ist. Das Überschreiben von Deinit ist in Ordnung: "Da die Zuordnung einer Instanz erst nach dem Aufruf ihres Deinitialisierers aufgehoben wird, kann ein Deinitialisierer auf alle Eigenschaften der Instanz zugreifen, auf die er aufgerufen wird, und sein Verhalten basierend auf diesen Eigenschaften ändern (z. B. nach dem Namen von a suchen) Datei, die geschlossen werden muss). " Deinit aufzurufen ist nicht in Ordnung
Dan Rosenstark
7

Swift 4.2

Beobachter hinzufügen-

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

Beobachter entfernen-

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

Ereignis behandeln-

@objc func handleEvent() {
}
Abhishek Jain
quelle
5

Mit Swift 4 weist Apple über eine neue Compiler-Warnung darauf hin, dass wir die Verwendung #selectorin diesem Szenario vermeiden . Folgendes ist viel sicherer, um dies zu erreichen:

Erstellen Sie zunächst eine faule Variable, die von der Benachrichtigung verwendet werden kann:

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

Wenn Sie die tatsächliche Meldung enthalten erfordern werden, ersetzen Sie einfach die _mit notification.

Als Nächstes richten wir die Benachrichtigung ein, um zu beobachten, ob die App aktiv wird.

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

Die große Änderung hier ist, dass #selectorwir anstelle von a jetzt die oben erstellte var aufrufen. Dies kann Situationen beseitigen, in denen ungültige Selektorabstürze auftreten.

Schließlich entfernen wir den Beobachter.

func removeObserver() {
    NotificationCenter.default.removeObserver(self, name: .UIApplicationDidBecomeActive, object: nil)
}
CodeBender
quelle
1
#selectorkann eine Methode aufrufen, @objcdie in Swift 4 als Attribut deklariert ist.
AnBisw
1
Die Verwendung ist falsch, removeObserver(selfda beim Hinzufügen eines Beobachters kein Selbst zugewiesen wurde. Sie sollten let observer = NotificationCenter.default.addObserverdannremoveObserver(observer
Yan Kalbaska
Danke @CodeBender Ich kannte diese Funktion noch nicht und sie entfernt (endlich) die @objc. Wenn ich es jedoch versuche, wird in der Konsole eine Warnung angezeigt (Xcode 11.3.1 (11C504), Swift 13.3): BackgroundTask kann nicht beendet werden: Es gibt keine Hintergrundaufgabe mit der Kennung. Auch wenn ich den Beobachter in einer Variablen als NSObjectProtocol speichere.
Palme
Trotzdem bekomme ich auch die Warnung, wenn ich die @objcVariante benutze .
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
    }
Gurjinder Singh
quelle
0

Der kombinierte Weg:

import Combine

var cancellables = Set<AnyCancellable>()
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)
    .sink { notification in
            // do stuff
    }.store(in: &cancellables)
ollie
quelle