2017-02-01 93 views
10

我經常這樣做,弱自我去哪裏?

let when = DispatchTime.now() + 2.0 
DispatchQueue.main.asyncAfter(deadline: when) { 
    beep() 
} 

,並在一個應用程序,我們經常這樣做

tickle.fresh(){ 
    msg in 
    paint() 
} 

但如果你

let when = DispatchTime.now() + 2.0 
DispatchQueue.main.asyncAfter(deadline: when) { 
    tickle.fresh(){ 
     msg in 
     paint() 
    } 
} 
當然

你必須做

let when = DispatchTime.now() + 2.0 
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in 
    tickle.fresh(){ 
     msg in 
     self?.paint() 
    } 
} 

或者,也許這

let when = DispatchTime.now() + 2.0 
DispatchQueue.main.asyncAfter(deadline: when) { 
    tickle.fresh(){ 
     [weak self] msg in 
     self?.paint() 
    } 
} 

或者也許這

let when = DispatchTime.now() + 2.0 
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in 
    tickle.fresh(){ 
     [weak self] msg in 
     self?.paint() 
    } 
} 

W¯¯牛逼^ h應該怎麼辦?

所有三個建議似乎完美地工作。這裏有什麼意思的深度?哪一個應該做?

而在最後一個,爲什麼你不得不說像[weak self?],因爲它是?

注 - 對不起,如果我不明確的,寓意是

func paint() { 
    paintSomething 

    let t = DispatchTime.now() + 2.0 
    DispatchQueue.main.asyncAfter(deadline: t) { weak maybe 
     tickle.fresh(){ weak maybe 
      guard self != nil else { 
       print("retired correctly!! hooray! thanks SO!") 
       return 
      } 
      self?.paint() 
     } 
    } 
} 

因此,我們將(比如,要求從雲遊戲信息,然後)油漆,等待兩秒鐘,這樣就夠了一次又一次;但當然你希望這個到一旦視圖控制器消失就完全停止

  • 一個問............是一個強參考弱參考,弱或強參考?

注:在我的例子,tickle.fresh(){}只是調用一個單身或東西:,因爲它發生,它並不特別使用self。所以,你可以這樣做:

所有的
func paint() { 
    paintSomething 

    let t = DispatchTime.now() + 2.0 
    DispatchQueue.main.asyncAfter(deadline: t) { [weak self] _ in 
     guard self != nil else { 
      print("retire early, don't even bother going to the cloud!") 
      print("thanks, SO!") 
      return 
     } 
     tickle.fresh(){ [weak self] _ in 
      guard self != nil else { 
       print("went to the cloud, then got retired!") 
       print("thanks, SO!") 
       return 
      } 
      self?.paint() 
     } 
    } 
} 

回答

27

首先,請注意,您一般不需要擔心保留週期與DispatchQueue.main.asyncAfter,當封閉將在一些點執行。因此,無論您是否輕微捕獲self,您都不會創建永久保留週期(假設tickle.fresh也不會)。

無論你是否在asyncAfter閉包上放置了[weak self]捕獲列表,完全取決於是否要在調用閉包之前(在設置的時間之後)保留self。如果你不需要self直到關閉被叫,那麼把[weak self]保持在,如果你這樣做,那麼不要把它放進去。

您是否將[weak self]放在內閉合件上(傳遞給tickle.fresh的那個閉合件)取決於您是否已經在外閉合件中弱拍self。如果你沒有,那麼你可以把[weak self],以防止內封閉保留它。然而如果外圍封閉已經弱勢俘獲self,那麼內部封閉將會有已經self有一個弱引用,因此加入內部封閉[weak self]將沒有任何效果。

因此,要總結:


DispatchQueue.main.asyncAfter(deadline: .now() + 2) { 
    tickle.fresh { msg in 
     self.paint() 
    } 
} 

self將由外部和內部閉合都被保留。


DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in 
    tickle.fresh { msg in 
     self?.paint() 
    } 
} 

self不會被任一閉合保留。


DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in 
    tickle.fresh { [weak self] msg in 
     self?.paint() 
    } 
} 

同上,附加[weak self]用於內封閉件具有沒有影響,因爲self已經弱通過外罩捕獲。


DispatchQueue.main.asyncAfter(deadline: .now() + 2) { 
    tickle.fresh { [weak self] msg in 
     self?.paint() 
    } 
} 

self將由外罩被保留,而不是內罩。


當然,這也許是因爲你不想self由外罩被保留,但你希望它由內罩被保留。在這種情況下,你可以以持有的強引用self,當你可以再內罩捕捉外部封閉聲明一個局部變量:現在

DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in 
    guard let strongSelf = self else { return } 
    tickle.fresh { msg in 
     strongSelf.paint() 
    } 
} 

self不會被保留活通過外部封閉,但一旦被調用,如果self仍然存在,它將通過內部封閉維持存活直到封閉被釋放。


迴應:

是一個強引用弱引用,弱或強的參考?

弱引用實現爲可選值,它們是值類型。因此,您不能直接有一個強烈的參考 - 而是你首先必須解開它,然後強烈參考底層實例。在這種情況下,你只需要處理一個強大的參考(完全像我上面的示例strongSelf)。然而,如果一個弱引用是盒裝(這種情況發生在關閉捕獲 - 值類型將被放入堆分配框中) - 那麼你確實可以有一個強有力的參考框。這個效果等同於對原始實例的弱引用,你只是有一點額外的間接點。

事實上,這是恰好是在外部閉包弱捕獲self並且內部閉包'強烈捕獲'弱引用的例子中發生了什麼。結果是這兩個封閉都保留了self

+0

Bravo!這需要一些思考!在*處,「自我將被外部封閉保留,而不是內部封閉」。* ......實際上,這是否意味着「它會再做一次」(「即使視圖控制器在兩秒內消失」 )但這是它會做的最後一個「.. ??!?? ?? – Fattie

+0

* wait * ..在當前最終代碼示例的第二行中,是否應該是'self!'?因爲「該代碼片段的第一行的自我」是一個可選的權利? – Fattie

+1

@JoeBlow這意味着'self'會被外層閉包保持活動狀態,但是一旦它被執行,就可以在內層閉包執行前(假設它是異步執行的)釋放它。在最後一個例子中,我使用可選的綁定和'guard let'來解開虛弱的'self',給了我一個很強的參考:) – Hamish