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!

Author: Fattie, 2017-02-01

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.

 162
Author: Hamish,
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