Kiedy wykonać ten kod:NSTimer zarządzanie pamięcią
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
muszę nil nim lub zwolnić go ot co za zarządzanie pamięcią?
Używam ARC
Kiedy wykonać ten kod:NSTimer zarządzanie pamięcią
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
muszę nil nim lub zwolnić go ot co za zarządzanie pamięcią?
Używam ARC
Tak, NSTimer
będzie utrzymywać silne odniesienie do target
, co może powodować (szczególnie w powtarzających się zegarach) silne cykle odniesienia (a.k.a. cykle zatrzymania). W twoim przykładzie zegar nie jest jednak powtarzany, a opóźnienie wynosi tylko 0,5, więc najgorszy scenariusz oznacza, że będziesz mieć silny cykl odniesienia, który automatycznie ustąpi w ciągu 0,5 sekundy.
Ale częstym przykładem nierozwiązanego mocnej cyklu odniesienia byłoby mieć UIViewController
z właściwością NSTimer
który powtarza się, ale ponieważ NSTimer
ma silne odniesienie do UIViewController
, kontroler będzie w końcu jest zachowana.
Tak więc, jeśli przechowujesz NSTimer
jako zmienną instancji, to tak, powinieneś invalidate
, aby rozwiązać silny cykl odniesienia. Jeśli po prostu dzwonisz pod numer scheduledTimerWithTimeInterval
, ale nie zapisujesz go do zmiennej instancji (jak można wywnioskować z twojego przykładu), wtedy silny cykl odniesienia zostanie rozwiązany po zakończeniu NSTimer
.
I, przy okazji, jeśli masz do czynienia z powtarzającymi się NSTimers
, nie próbuj invalidate
nich dealloc
od właściciela NSTimer
ponieważ dealloc
oczywiście nie będzie się aż silny cykl odniesienia został rozwiązany. Na przykład w przypadku UIViewController
można to zrobić w viewDidDisappear
.
Przy okazji, Advanced Memory Management Programming Guide wyjaśnia, czym są silne cykle odniesienia. Najwyraźniej jest to sekcja, w której opisują poprawne użycie słabych odniesień, co nie ma tu zastosowania (ponieważ nie masz kontroli nad tym, że NSTimer
używa silnych odniesień do celu), ale wyjaśnia pojęcia z silnym cyklem referencyjnym ładnie.
Jeśli nie chcesz NSTimer
utrzymać silne odniesienie do self
, w MacOS i iOS 10.12 10 lub później, można użyć odwzorowanie bloku, a następnie użyć weakSelf
wzoru:
typeof(self) __weak weakSelf = self;
[NSTimer scheduledTimerWithTimeInterval:0.5 repeats:false block:^(NSTimer * _Nonnull timer) {
[weakSelf showButtons];
}];
Przy okazji zauważam, że dzwonisz pod numer showButtons
. Jeśli starasz się po prostu pokazać niektóre kontrole na widoku, można wyeliminować stosowanie NSTimer
całkowicie i zrobić coś takiego:
self.button1.alpha = 0.0;
self.button2.alpha = 0.0;
[UIView animateWithDuration:0.25
delay:0.5
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
self.button1.alpha = 1.0;
self.button2.alpha = 1.0;
}
completion:nil];
nie cierpią na problemy zachowują NSTimer
obiektów i wykonuje zarówno opóźnienie, a także pełne wdzięku przedstawienie przycisku (ów) w jednym komunikacie.Jeśli robisz dodatkowe przetwarzanie w metodzie showButtons
, możesz umieścić to w bloku completion
.
Jeśli zapisujesz je w nieruchomości, to tak, trzeba zrobić, aby ustawić go do zera po opalane selektora.
Można go również bezpiecznie zapisać na wypadek, gdyby twoja klasa została zwolniona z dowolnego powodu, abyś mógł [timer invalidate]
, jeśli potrzebujesz.
Jeśli się, że właściwość 'weak', nie masz do' zerowe to sam. Uruchamia się automatycznie po wystrzeleniu (zakładając, że nie powtarza się). – Rob
Tak, można użyć: myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO];
a potem w swoim viewDidDisappear [myTimer invalidate]
Świetna odpowiedź, ale być może nie wyjaśniłam, że tak naprawdę nie deklamuję jej w pliku .h z zegarem NSTimer *, po prostu dodajemy ten kod do pliku .m, więc nie mogę go unieważnić ani zlikwidować . Czy w takim przypadku nadal jest dobrze, jeśli korzystam z timera, czy lepiej użyć kodu, który mi podałeś? – Alessandro
@Alessandro Tak naprawdę przypuszczałem, że nie utrzymałeś ivar dla timera. Ale oczywiście, jeśli chcesz "unieważnić" w 'viewWillDisappear', będziesz musiał to zrobić. (Na marginesie, nie musisz umieszczać prywatnych znaków iv w twoim .h; rozszerzenie klasy prywatnej jest lepsze.) I kilka razy wspomniałeś o ustawianiu 'NSTimer' na' zero'. Należy pamiętać, że nie rozwiązuje to silnego cyklu odniesienia. Timer musi albo zakończyć (i nie musi się powtarzać), albo musisz "unieważnić" (używając twojego nowego ivar). – Rob