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 stelle ich das [[NSNotificationCenter defaultCenter] removeObserver:self]
in dieser Klasse ein? Ich weiß, dass ich es für a UIViewController
in die viewDidUnload
Methode einfügen kann. Was muss also getan werden, wenn ich gerade eine objektive c-Klasse erstellt habe?
-(void)dealloc
und dann hinzufügenremoveObserser:self
. Dies ist die am meisten empfohlene Methode, umremoveObservers:self
dealloc
Methode in iOS 6 einzufügen?Antworten:
Die generische Antwort wäre "sobald Sie die Benachrichtigungen nicht mehr benötigen". Dies ist offensichtlich keine zufriedenstellende Antwort.
Ich würde empfehlen, dass Sie einen Anruf hinzufügen ,
[notificationCenter removeObserver: self]
in Verfahrendealloc
dieser Klassen, die Sie als Beobachter verwenden möchten, da es die letzte Chance zu austragen Beobachter sauber ist. Dies schützt Sie jedoch nur vor Abstürzen, da das Benachrichtigungscenter tote Objekte benachrichtigt. Es kann Ihren Code nicht vor dem Empfang von Benachrichtigungen schützen, wenn sich Ihre Objekte noch nicht / nicht mehr in einem Zustand befinden, in dem sie die Benachrichtigung ordnungsgemäß verarbeiten können. Dafür ... Siehe oben.Bearbeiten (da die Antwort mehr Kommentare zu zeichnen scheint, als ich gedacht hätte) Ich versuche hier nur zu sagen: Es ist wirklich schwierig, allgemeine Ratschläge zu geben, wann es am besten ist, den Beobachter aus dem Benachrichtigungscenter zu entfernen, da dies davon abhängt:
Der beste allgemeine Rat, den ich finden kann: Zum Schutz Ihrer App.
removeObserver:
Tanzen Sie gegen mindestens einen möglichen Fehler,dealloc
da dies der letzte Punkt (im Leben des Objekts) ist, an dem Sie dies sauber tun können. Was dies nicht bedeutet ist: "Verschieben Sie die Entfernungdealloc
einfach, bis sie aufgerufen wird, und alles wird in Ordnung sein". Entfernen Sie stattdessen den Beobachter , sobald das Objekt nicht mehr bereit (oder erforderlich) ist, Benachrichtigungen zu erhalten . Das ist genau der richtige Moment. Da ich die Antworten auf eine der oben genannten Fragen nicht kenne, kann ich leider nicht einmal erraten, wann dieser Moment sein würde.Sie können
removeObserver:
ein Objekt immer mehrmals sicher sichern (und alle bis auf den ersten Anruf mit einem bestimmten Beobachter sind Nops). Also: Überlegen Siedealloc
, ob Sie es (erneut) tun möchten, um sicherzugehen, aber in erster Linie: Machen Sie es zum richtigen Zeitpunkt (der von Ihrem Anwendungsfall bestimmt wird).quelle
dealloc
ist nur eine letzte Verteidigungslinie gegen das Abstürzen der App aufgrund eines späteren Zugriffs auf ein nicht zugeordnetes Objekt. Der richtige Ort, um die Registrierung eines Beobachters aufzuheben, ist normalerweise an einem anderen Ort (und oft viel früher im Lebenszyklus des Objekts). Ich versuche hier nicht zu sagen "Hey, mach es einfachdealloc
und alles wird gut".viewWillDisappear
" Das Problem bei der Abgabe eines konkreten Hinweises ist, dass es wirklich davon abhängt, welche Art von Objekt Sie als Beobachter für welche Art von Ereignis registrieren. Es mag die richtige Lösung sein, die Registrierung eines Beobachters inviewWillDisappear
(oderviewDidUnload
) fürUIViewController
s aufzuheben, aber das hängt wirklich vom Anwendungsfall ab.Seit iOS 9 müssen keine Beobachter mehr entfernt werden.
https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter
quelle
Hinweis: Dies wurde getestet und funktioniert zu 100%
Schnell
PresentedViewController
Ziel c
In
iOS 6.0 > version
ist es besser, Beobachter zu entfernen,viewWillDisappear
da dieviewDidUnload
Methode veraltet ist.Es ist um ein Vielfaches besser,
remove observer
wenn die Ansicht aus dem entfernt wurdenavigation stack or hierarchy
.PresentedViewController
quelle
viewWillAppear:
removeObserver:self
eines derUIViewController
Lebenszyklusereignisse ruiniert fast garantiert Ihre Woche. WeitereremoveObserver
AnrufeviewWillDisappear
wie angegeben ist definitiv der richtige Weg, wenn der Controller über präsentiert wirdpushViewController
. Wenn Sie siedealloc
stattdessen eingeben,dealloc
wird sie - zumindest meiner Erfahrung nachWenn der Beobachter einem Ansichts-Controller hinzugefügt wird , empfehle ich dringend, ihn hinzuzufügen
viewWillAppear
und zu entfernenviewWillDisappear
.quelle
viewWillAppear
undviewWillDisappear
für viewController?dealloc
sofort aufgerufen. Das Zurückkehren in den Ansichts-Controller kann dann zu mehreren Benachrichtigungen führen, wenn Beobachter in Initialisierungsbefehlen hinzugefügt wird.quelle
self
after[super dealloc]
macht mich nervös ... (selbst wenn es unwahrscheinlich ist, dass der Empfänger den Zeiger in irgendeiner Weise dereferenziert, wissen Sie nie, wie sie implementiert wurdenNSNotificationCenter
)[super dealloc]
muss immer die letzte Aussage Ihrerdealloc
Methode sein. Es zerstört dein Objekt; Nachdem es ausgeführt wird, haben Sie keine gültigeself
mehr. / cc @Dirk[super dealloc]
nach nicht mehr benötigtIm Allgemeinen habe ich es in die
dealloc
Methode eingefügt.quelle
Verwenden Sie schnell deinit, da kein Dealloc verfügbar ist:
Schnelle Dokumentation:
quelle
* Bearbeiten: Dieser Hinweis gilt für iOS <= 5 (auch dort sollten Sie hinzufügen
viewWillAppear
und entfernenviewWillDisappear
- der Hinweis gilt jedoch, wenn Sie aus irgendeinem Grund den Beobachter hinzugefügt habenviewDidLoad
).Wenn Sie den Beobachter hinzugefügt haben
viewDidLoad
, sollten Sie ihn in beidendealloc
und entfernenviewDidUnload
. Andernfalls fügen Sie es zweimal hinzu, wennviewDidLoad
es danach aufgerufen wirdviewDidUnload
(dies geschieht nach einer Speicherwarnung). Dies ist in iOS 6 nicht erforderlich, woviewDidUnload
es veraltet ist und nicht aufgerufen wird (da Ansichten nicht mehr automatisch entladen werden).quelle
Meiner Meinung nach macht der folgende Code in ARC keinen Sinn :
In iOS 6 macht es auch keinen Sinn, Beobachter zu entfernen
viewDidUnload
, da dies jetzt veraltet ist.Zusammenfassend mache ich es immer in
viewDidDisappear
. Es hängt jedoch auch von Ihren Anforderungen ab, genau wie @Dirk sagte.quelle
Ich glaube ich habe eine gefunden verlässliche Antwort gefunden ! Ich musste, da die obigen Antworten mehrdeutig sind und widersprüchlich erscheinen. Ich habe Kochbücher und Programmierhandbücher durchgesehen.
Erstens der Stil von
addObserver:
inviewWillAppear:
undremoveObserver:
viewWillDisappear:
funktioniert in für mich nicht (ich habe ihn getestet), da ich eine Benachrichtigung in einem untergeordneten Ansichtscontroller poste, um Code im übergeordneten Ansichtscontroller auszuführen. Ich würde diesen Stil nur verwenden, wenn ich die Benachrichtigung im selben View Controller posten und abhören würde.Die Antwort, auf die ich mich am meisten verlassen werde, fand ich in der iOS-Programmierung: Big Nerd Ranch Guide 4th. Ich vertraue den BNR-Leuten, weil sie iOS-Schulungszentren haben und nicht nur ein weiteres Kochbuch schreiben. Es ist wahrscheinlich in ihrem besten Interesse, genau zu sein.
BNR Beispiel eins:
addObserver:
ininit:
,removeObserver:
indealloc:
BNR-Beispiel zwei:
addObserver:
inawakeFromNib:
,removeObserver:
indealloc:
… Beim Entfernen des Beobachters in
dealloc:
sie diese nicht[super dealloc];
Ich hoffe das hilft der nächsten Person…
Ich aktualisiere diesen Beitrag, da Apple jetzt fast vollständig auf Storyboards verzichtet hat, sodass die oben genannten möglicherweise nicht für alle Situationen gelten. Das Wichtigste (und der Grund, warum ich diesen Beitrag überhaupt hinzugefügt habe) ist, darauf zu achten, wenn Sie
viewWillDisappear:
angerufen werden. Es war nichts für mich, als die Anwendung in den Hintergrund trat.quelle
Die akzeptierte Antwort ist nicht sicher und kann zu einem Speicherverlust führen. Bitte lassen Sie die Abmeldung im Dealloc, aber melden Sie sich auch in viewWillDisappear ab (das ist natürlich, wenn Sie sich in viewWillAppear registrieren). :) :)
quelle
Es ist wichtig zu beachten, dass dies auch
viewWillDisappear
aufgerufen wird, wenn der View Controller eine neue UIView präsentiert. Dieser Delegat gibt lediglich an, dass die Hauptansicht des View Controllers auf dem Display nicht sichtbar ist.In diesem Fall kann die Freigabe der Benachrichtigung
viewWillDisappear
unpraktisch sein, wenn wir die Benachrichtigung verwenden, damit die UIview mit dem übergeordneten Ansichtscontroller kommunizieren kann.Als Lösung entferne ich den Beobachter normalerweise mit einer dieser beiden Methoden:
Aus ähnlichen Gründen muss ich beim ersten Ausstellen der Benachrichtigung berücksichtigen, dass jedes Mal, wenn eine Ansicht mit über dem Controller
viewWillAppear
angezeigt wird, die 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, kann ich das Problem vermeiden, indem ich die Benachrichtigung entferne, bevor ich sie hinzufüge:quelle
SWIFT 3
Es gibt zwei Fälle, in denen Benachrichtigungen verwendet werden: - Sie werden nur benötigt, wenn der Ansichts-Controller auf dem Bildschirm angezeigt wird. - Sie werden immer benötigt, auch wenn der Benutzer einen anderen Bildschirm über Strom geöffnet hat.
Für den ersten Fall ist der richtige Ort zum Hinzufügen und Entfernen von Beobachtern:
für den zweiten Fall ist der richtige Weg:
Und nie setzen
removeObserver
indeinit{ ... }
- es ist ein Fehler!quelle
quelle