NSTimer memory management
Wenn ich diesen code ausführen:
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
brauche ich zu null oder zu veröffentlichen, ot, was für Speicher-management?
Bin ich mit der ARC
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja,
NSTimer
pflegen einen starken Bezug zu dentarget
verursachen kann (vor allem in sich wiederholenden Timer) starken Bezug Zyklen (ein.k.ein. retain-Zyklen). In deinem Beispiel, wenn der timer nicht wiederholt wird, und verzögert nur 0,5, also worst-case-Szenario, Sie haben eine starke Referenz-Zyklus, der automatisch lösen sich in 0,5 Sekunden.Aber ein gängiges Beispiel für eine ungelöste starken Referenz-Zyklus wäre eine
UIViewController
mit einemNSTimer
Eigenschaft, die wiederholt, aber, weil dieNSTimer
hat einen starken Bezug zurUIViewController
der controller am Ende wird beibehalten.So, wenn Sie halten die
NSTimer
wie eine Instanzvariable, dann, ja, dann sollten Sieinvalidate
es zu beheben, die starke Referenz-Zyklus. Wenn Sie nur den Aufruf derscheduledTimerWithTimeInterval
, aber nicht speichern, können Sie mit einer Instanz-variable (als könnte man folgern aus deinem Beispiel), dann Ihre starke Referenz-Zyklus wird behoben werden, wenn dieNSTimer
abgeschlossen ist.Und, by the way, wenn Sie ' re Umgang mit sich wiederholenden
NSTimers
, versuchen Sie nicht zuinvalidate
Sie indealloc
der Besitzer desNSTimer
weil diedealloc
wird offensichtlich nicht aufgerufen werden, bis die starke Referenz-Zyklus wird behoben. Im Falle einerUIViewController
zum Beispiel, Sie könnte es tun, inviewDidDisappear
.Durch die Art und Weise, die Advanced Memory Management Programming Guide erklärt, was starke Referenz-Zyklen sind. Klar, das ist in einem Abschnitt, in dem Sie beschreiben, der richtigen Verwendung von schwachen Referenzen, die nicht hier anwendbar (weil Sie keine Kontrolle über die Tatsache, dass
NSTimer
verwendet starke Verweise auf das Ziel), aber es erklärt die Konzepte der starken Referenz-Zyklen schön.Wenn Sie nicht möchten, dass Ihre
NSTimer
halten einen starken Bezug zuself
im macOS 10.12 und iOS 10 oder höher, können Sie den block Wiedergabe und verwenden Sie dann dieweakSelf
Muster:By the way, ich merke, dass Sie anrufen
showButtons
. Wenn Sie versuchen, nur zeigen einige Kontrollen auf Ihrer Ansicht, Sie könnten um die Verwendung derNSTimer
zusammen und tun Sie etwas wie:Diese nicht leiden, behalten Fragen der
NSTimer
Objekte, und führt sowohl die Verzögerung als auch die anmutige zeigt der button(s) alle in einer Anweisung. Wenn Sie zusätzliche Verarbeitung in IhremshowButtons
Methode können Sie setzen, dass in dercompletion
block.invalidate
imviewWillDisappear
werden Sie haben, dies zu tun. (Als beiseite, die Sie nicht haben, um private ivars in Ihr .h; private class extension ist besser.) Und ein paar mal, die Sie erwähnt haben über die Einstellung einesNSTimer
zunil
. Bitte beachten Sie, dass dies nicht beheben starke Referenz-Zyklus. Die timer entweder muss entweder vollständig (und nicht wiederholt), oder Sie müsseninvalidate
(mit Ihrem neuen ivar).nil
und eineif timer != nil
oder, das ist unnötig und macht gerade eine!timer.isValid
ist genug? in anderen Worten, ist es keine Verwendung zu tuntimer = nil
? In Ihrem früheren Kommentar, auf den Sie schon sagte, es hat nichts mit dem Speicher-management, so Frage ich mich, warum viele Entwickler machen weiter währendisValid
erhöht die Klarheit...Wenn Sie es speichern in eine Immobilie, dann ja, Sie müssen, um es zu null, nachdem er feuerte den Selektor.
Ist es auch sicher zu speichern, im Falle, wenn Ihre Klasse wird freigegeben, aus welchem Grund auch immer, so dass Sie
[timer invalidate]
wenn Sie benötigen.weak
Sie nicht haben, umnil
es selbst. Es wird automatisch die neue Version selbst, nachdem es ausgelöst (vorausgesetzt, es wurde nicht wiederholt).invalidate
obligatorisch wird. Sonst-Schleife die Durchlaufen werden, behalten Sie Ihren Zeiger auf der viewController dieweak
ly deutete auf den timerJa, Sie können verwenden:
myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
Und dann in deinem viewDidDisappear
[myTimer invalidate]
Verwenden Sie die neue Methode der Timer, der die Verschlüsse verwendet