2017-08-09 10 views
1

私は、閉鎖に[weak self]または[unowned self]を使用する必要があるとき、StackOverflowに関するいくつかの議論を読んだ。我々は我々だけで明示的に閉鎖内selfを使用しているときスウィフトが任意のエラーや警告は表示されませんので、どちらもそれらのを使用する必要がないとき[弱い自己]も[所有していない自己]も使用しないでください。

はしかし、いずれの場合もあります。

たとえば、weakまたはunownedをここで使用しますか?

UIView.animate(withDuration: 0.3) { 
    self.view.alpha = 0.0 
} 
+1

**? –

+1

[Strong Reference Cycles for Closures](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097)をご覧ください。 -CH20-ID56)Swiftプログラミング言語ガイドの一部です。 –

答えて

1

クロージャが強い参照サイクルを引き起こす可能性がある場合は、[弱い自己]または[無所有の自己]を使用する必要があります。

あなたは自己のプロパティに閉鎖を割り当てる、あなたが自己または閉鎖自体の内部自己のプロパティを参照する場合、これが発生する可能性があります。クロージャは参照型です。したがって、通常のクラスを使用した場合と同じように、本質的に同じ参照が強い参照に適用されます。

あなたの例については、あなたがselfが参照するクラス内の変数に閉鎖を割り当てないので、[weak self]または[unowned self]の必要は、ありませんので、強い基準サイクルがありません。

詳細については、Swiftプログラミング言語ガイドのStrong Reference Cycles for Closuresを参照してください。ここで強い参照サイクルが閉鎖によって引き起こされ得る場合の言及リンクの例である:asHTMLの閉鎖に[unowned self]なし

class HTMLElement { 

    let name: String 
    let text: String? 

    lazy var asHTML:() -> String = { 
     if let text = self.text { 
      return "<\(self.name)>\(text)</\(self.name)>" 
     } else { 
      return "<\(self.name) />" 
     } 
    } 

    init(name: String, text: String? = nil) { 
     self.name = name 
     self.text = text 
    } 

    deinit { 
     print("\(name) is being deinitialized") 
    } 

} 

、強い基準サイクルは、asHTMLに割り当てられた閉鎖によって引き起こされるであろう。以下にasHTMLの実装を変更すると、この問題を解決:

** ** **それらを使用するときのための回答に記載されていないいずれの場合であっても
lazy var asHTML:() -> String = { 
    [unowned self] in 
    if let text = self.text { 
     return "<\(self.name)>\(text)</\(self.name)>" 
    } else { 
     return "<\(self.name) />" 
    } 
} 
+0

さて、asHTML varの2つの実装の違いは何ですか? – Legonaftik

+0

誤って '[unowned self]'を正しい実装から除外し、今修正しました。 –

1

これは、多少の意見に基づいているので、私は私の意見を与えるでしょう:)

私は、一般的に同期をベースにします。クロージャがAsyncの場合、closeが呼び出されたときに呼び出しインスタンスが存在しなくなるため、[weak self]を使用する必要があります。クロージャが同期している場合、それは不要であり、強力な参照をキャプチャしても問題ありません。

には、インスタンスを有効にしておくと(例えば、あなたのViewアニメーションの場合など)、クロージャーとあなたの使用法が合理的に期待できるクロージャーも含まれていますそれは未来のある時点で理論的に破綻する可能性があります。安全性が低く、将来のメンテナンスがより困難/危険になります。

UIView.animateのような確立された予測可能なAPIの場合、私は個人的には簡潔にするために強い自己を使用する傾向がありますが、これは自分自身で行う必要があり、使い方によって異なります。

また、コメントに記載されているように、これは関数クロージャにも当てはまります。クロージャーを別の変数のプロパティに代入するのには、異なる一連の問題があります。

私は、弱参照クロージャのアプローチを採用しています。これは、単に、タイプ内で別のメソッドを呼び出すことです。

thing.doSomethingWithAClosure() { [weak self] 
    self?.doSomething() 
} 

ロジックを単純化し、より機能的な/モジュラーコードも実行します。

関連する問題