Dokąd zmierza słaba jaźń?
Często to robię.]}
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
beep()
}
I w jednej aplikacji często to robimy
tickle.fresh(){
msg in
paint()
}
Ale jeśli zrobisz to
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
tickle.fresh(){
msg in
paint()
}
}
Oczywiście, że musisz to zrobić
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in
tickle.fresh(){
msg in
self?.paint()
}
}
A może to
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
tickle.fresh(){
[weak self] msg in
self?.paint()
}
}
a może to
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in
tickle.fresh(){
[weak self] msg in
self?.paint()
}
}
W T H powinniśmy zrobić?
Wszystkie trzy sugestie wydają się działać idealnie. Jaka jest tu cała głębia znaczenia? A co należy zrobić? Jest silnym odniesieniem do słabego odniesienie, słabe czy mocne odniesienie? Być czy nie być? Oto jest pytanie!
1 answers
Przede wszystkim należy pamiętać, że generalnie nie trzeba się martwić o zachowanie cykli z DispatchQueue.main.asyncAfter
, ponieważ zamknięcie zostanie wykonane w jakimś punkcie. Dlatego bez względu na to, czy słabo uchwycisz self
, nie stworzysz stałego cyklu zatrzymywania(zakładając, że tickle.fresh
również nie).
To, czy umieścisz [weak self]
listę przechwytywania na zewnętrznej asyncAfter
zamknięcia, zależy całkowicie od tego, czy chcesz, aby self
zostało zachowane do momentu wywołania zamknięcia (po ustawieniu czasu). Jeśli nie musisz self
pozostać przy życiu, dopóki zamknięcie nie zostanie wywołane, włóż [weak self]
, jeśli to zrobisz, to nie wkładaj tego.
To, czy umieścisz [weak self]
na wewnętrznym zamknięciu (tym, które zostało przekazane tickle.fresh
) zależy od tego, czy już słabo uchwyciłeś self
w zewnętrznym zamknięciu. Jeśli tego nie zrobiłeś, możesz umieścić [weak self]
, aby zapobiec zatrzymaniu wewnętrznego zamknięcia. Jeśli jednak zewnętrzne zamknięcie zostało już słabo uchwycone self
, to wewnętrzne zamknięcie będzie już miało słabe odniesienie do self
, a więc dodanie [weak self]
do wewnętrznego zamknięcia nie będzie miało wpływu.
Podsumowując:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { msg in
self.paint()
}
}
self
zostanie zachowany zarówno przez zewnętrzne, jak i wewnętrzne zamknięcie.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { msg in
self?.paint()
}
}
self
nie zostaną zatrzymane przez żadne zamknięcie.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { [weak self] msg in
self?.paint()
}
}
Podobnie jak wyżej, dodatkowe [weak self]
dla zamknięcia wewnętrznego nie ma wpływu, ponieważ self
jest już słabo uchwycone przez zamknięcie zewnętrzne.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { [weak self] msg in
self?.paint()
}
}
self
zostanie zachowana przez zewnętrzne zamknięcie, ale nie wewnętrzne zamknięcie.
Oczywiście, może być tak, że nie chcesz self
być zatrzymanym przez zewnętrzne zamknięcie, ale chcesz być zatrzymanym przez wewnętrzne zamknięcie. W takich przypadkach można zadeklarować zmienną lokalną w zewnętrznym zamknięciu, aby mieć silne odniesienie do self
, Kiedy można następnie przechwycić w wewnętrznym zamknięciu:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
guard let strongSelf = self else { return }
tickle.fresh { msg in
strongSelf.paint()
}
}
Teraz, self
nie zostanie utrzymana przy życiu przez zewnętrzne zamknięcie, ale gdy zostanie wywołane, Jeśli self
nadal istnieje, to być utrzymywane przy życiu przez wewnętrzne zamknięcie, dopóki Zamknięcie to nie zostanie rozdzielone.
W odpowiedzi na:
Czy mocne odniesienie do słabego odniesienia, słabe czy mocne odniesienie?
Słabe odwołania są implementowane jako opcje, które są typami wartości. Dlatego nie możesz bezpośrednio mieć silnego odniesienia do jednego z nich – zamiast tego najpierw musisz go rozpakować, a następnie wziąć silne odniesienie do podstawowej instancji. W tym przypadku jesteś po prostu radzenie sobie z silnym odniesieniem (dokładnie jak mój przykład powyżej z strongSelf
).
Jednakże, jeśli słaba Referencja jest boxed (dzieje się tak w przypadku closure capture – typ wartości zostanie umieszczony w polu przydzielonym stercie)-wtedy rzeczywiście możesz mieć silne odniesienie do tego pola. Efekt tego jest równoznaczny ze słabym odniesieniem do oryginalnej instancji, po prostu masz niewidoczny kawałek dodatkowego indrection.
W rzeczywistości jest to dokładnie co dzieje się w przykład, w którym zamknięcie zewnętrzne słabo wychwytuje self
, A Zamknięcie wewnętrzne "silnie wychwytuje" to słabe odniesienie. Efekt jest taki, że żadne zamknięcie nie zachowuje self
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-10 09:55:43