objective-c - notification - swift observer
Ziel C: Wo Beobachter für NSNotification entfernen? (10)
Ich habe eine objektive C-Klasse. Darin habe ich eine Init-Methode erstellt und darin eine NSNotification eingerichtet
//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(getData)
name:@"Answer Submitted"
object:nil];
Wo setze ich das [[NSNotificationCenter defaultCenter] removeObserver:self]
in dieser Klasse ein? Ich weiß, dass ich für einen UIViewController
kann es in der viewDidUnload
-Methode hinzufügen Also was muss getan werden, wenn ich gerade eine objektive c-Klasse erstellt?
Hinweis: Dies wurde getestet und funktioniert zu 100%
Schnell
override func viewWillDisappear(animated: Bool){
super.viewWillDisappear(animated)
if self.navigationController!.viewControllers.contains(self) == false //any other hierarchy compare if it contains self or not
{
// the view has been removed from the navigation stack or hierarchy, back is probably the cause
// this will be slow with a large stack however.
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
PräsentierterViewController
override func viewWillDisappear(animated: Bool){
super.viewWillDisappear(animated)
if self.isBeingDismissed() //presented view controller
{
// remove observer here
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
Ziel c
In iOS 6.0 > version
ist es besser, den Beobachter in viewWillDisappear
zu entfernen, da viewDidUnload
Methode viewDidUnload
veraltet ist.
[[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
Es ist oft besser, remove observer
zu remove observer
wenn die Ansicht aus dem navigation stack or hierarchy
.
- (void)viewWillDisappear:(BOOL)animated{
if (![[self.navigationController viewControllers] containsObject: self]) //any other hierarchy compare if it contains self or not
{
// the view has been removed from the navigation stack or hierarchy, back is probably the cause
// this will be slow with a large stack however.
[[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
}
}
PräsentierterViewController
- (void)viewWillDisappear:(BOOL)animated{
if ([self isBeingDismissed] == YES) ///presented view controller
{
// remove observer here
[[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
}
}
* edit: Dieser Hinweis gilt für iOS <= 5 (auch dort sollten Sie in viewWillAppear
hinzufügen und in viewWillAppear
entfernen - der Ratschlag gilt jedoch, wenn Sie aus viewDidLoad
Grund den Beobachter in viewDidLoad
hinzugefügt viewDidLoad
)
Wenn Sie den Beobachter in viewDidLoad
hinzugefügt viewDidLoad
, sollten Sie ihn sowohl in dealloc
als auch in dealloc
viewDidUnload
. Andernfalls fügen Sie es am Ende zweimal hinzu, wenn viewDidLoad
nach viewDidUnload
(dies geschieht nach einer Speicherwarnung). Dies ist in iOS 6 nicht erforderlich, wenn viewDidUnload
veraltet ist und nicht aufgerufen wird (weil die Ansichten nicht mehr automatisch entladen werden).
Die angenommene Antwort ist nicht sicher und könnte einen Speicherverlust verursachen. Bitte lassen Sie die Registrierung in dealloc aber auch abmelden in viewWillDisappear (das ist natürlich, wenn Sie sich in ViewWillAppear registrieren) .... Das ist, was ich schon immer getan habe und es funktioniert super! :)
Es ist wichtig zu beachten, dass viewWillDisappear
auch viewWillDisappear
wird, wenn der View-Controller eine neue UIView anzeigt. Dieser Delegat gibt lediglich an, dass die Hauptansicht des Ansichtscontrollers nicht auf dem Bildschirm angezeigt wird.
In diesem Fall ist es möglicherweise unangenehm, die Benachrichtigung in viewWillDisappear
, wenn wir die Benachrichtigung verwenden, um der UIview die Kommunikation mit dem übergeordneten Ansichtscontroller zu ermöglichen.
Als Lösung entferne ich normalerweise den Beobachter in einer der beiden folgenden Methoden:
- (void)viewWillDisappear:(BOOL)animated {
NSLog(@"viewController will disappear");
if ([self isBeingDismissed]) {
NSLog(@"viewController is being dismissed");
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
}
}
-(void)dealloc {
NSLog(@"viewController is being deallocated");
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
}
Aus ähnlichen Gründen, wenn ich die Benachrichtigung zum ersten Mal ausstelle, muss ich berücksichtigen, dass jedes Mal, wenn eine Ansicht mit über dem Controller viewWillAppear
wird, viewWillAppear
Methode ausgelöst wird. Dies erzeugt wiederum mehrere Kopien derselben Benachrichtigung. Da es keine Möglichkeit gibt, zu überprüfen, ob eine Benachrichtigung bereits aktiv ist, beseitige ich das Problem, indem ich die Benachrichtigung vor dem Hinzufügen lösche:
- (void)viewWillAppear:(BOOL)animated {
NSLog(@"viewController will appear");
// Add observers
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"imageGenerated" object:nil]; // This is added to avoid duplicate notifications when the view is presented again
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedImageFromCameraOrPhotolibraryMethodOnListener:) name:@"actionCompleted" object:nil];
}
Im Allgemeinen lege ich es in die dealloc
Methode.
In schnellem Gebrauch deinit, da dealloc nicht verfügbar ist:
deinit {
...
}
Schnelle Dokumentation:
Ein Deinitializer wird unmittelbar vor dem Aufheben einer Klasseninstanz aufgerufen. Sie schreiben Deinitializer mit dem Schlüsselwort deinit, ähnlich wie Initializer mit dem Schlüsselwort init geschrieben werden. Deinitializer sind nur für Klassen verfügbar.
In der Regel müssen Sie die manuelle Bereinigung nicht durchführen, wenn die Zuordnung der Instanzen aufgehoben wird. Wenn Sie jedoch mit Ihren eigenen Ressourcen arbeiten, müssen Sie möglicherweise einige zusätzliche Bereinigungen selbst durchführen. Wenn Sie beispielsweise eine benutzerdefinierte Klasse erstellen, um eine Datei zu öffnen und Daten darauf zu schreiben, müssen Sie möglicherweise die Datei schließen, bevor die Klasseninstanz freigegeben wird.
Seit iOS 9 müssen Beobachter nicht mehr entfernt werden.
In OS X 10.11 und iOS 9.0 werden NSNotificationCenter und NSDistributedNotificationCenter keine Benachrichtigungen mehr an registrierte Beobachter senden, die ihre Zuordnung aufheben können.
Wenn der Beobachter einem View-Controller hinzugefügt wird , empfehle ich dringend, ihn in viewWillAppear
hinzuzufügen und in viewWillAppear
entfernen.
-(void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
override func viewDidLoad() { //add observer
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector:#selector(Yourclassname.method), name: NSNotification.Name(rawValue: "NotificationIdentifier"), object: nil)
}
override func viewWillDisappear(_ animated: Bool) { //remove observer
super.viewWillDisappear(true)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "NotificationIdentifier"), object: nil)
}