2017-12-20 3 views
1

保持サイクルを追跡する際に問題があります。私はそれがイベントを購読する方法と関係があると思う。擬似コードは、このようなものです:クロージャとしての機能の使用は自己を保持していますか?

override func viewDidLoad() { 
    func handleEvent() { 
    self.doSomething() 
    } 

    subscribe("eventName", block: handleEvent) 
} 

deinit { 
    unsubscribe("eventName") 
} 

が、これは自己/私のViewControllerに保持サイクルを作成するのでしょうか?もしそうなら、私はどうすれば周りを回ることができますか?私がクロージャを使用していたなら、私は[弱い自己]を使うことができましたが、私は関数を渡すので、とにかく[弱い自己]同等物を使うのですか?

+0

この質問はクロージャについてですが、私はクロージャとして関数を使用することを求めています。弱い自己を関数で使うことはできません。 –

+0

あなたのコードを間違って読んで...私の悪い。ちょうど1秒 – PeejWeej

+1

あなたは保持サイクルがあるかどうかを判断するために、 'subscribe'が渡されたクロージャーと何をするのかを知る必要があります。それを格納せずに呼び出すか、別のクロージャーでキャプチャして保存すると( 'self'または' self'が強い参照を持つ)、保存サイクルはありません。それがストア/キャプチャを行う場合は、はい、保持サイクルがあります。あなたのコードを[mcve]に煮詰めることができれば、最も役に立ちます。 – Hamish

答えて

2

短いストーリーで、あなたのコードは参照を保持します。 (handleEvent-> viewDidLoad-> self)、http://blog.xebia.com/function-references-in-swift-and-retain-cycles/には、この問題を回避するための一般的な戦略があります。関数を宣言するのではなく、関数参照を作成することをお勧めします。

let eventHandler:() ->() = { [weak self] in 
    self?.doSomething() 
} 
subscribe("eventName", block: eventHandler) 
+1

これは本質的に私が言うつもりだったものです。 OPの構文質問への答えは、匿名関数(var値として割り当てられた関数を含む)がキャプチャリスト構文を許可し、名前付き関数宣言がそうでないことです。しかし、OPの状況が実際に保持サイクルを引き起こすかどうかは言うまでもありません。 OPは十分な情報を提供していない。 'subscribe'が何をし、' block'パラメータの運命が(Hamishが正しく指摘したように)何に依存し、OPはその情報を隠しています。 – matt

+0

@mattイベントが処理され、インスタンスがなくなった後にイベントが起動する必要があるかどうかを判断する必要があることは明らかです。関数参照を格納すると、これはいつでも起きないでしょう。 – PeejWeej

2

クラス内からプロパティまたはメソッドを参照すると、保持サイクルが作成されます。

class SomeClass { 
    val a: (block: (() ->()) ->()) = ... 

    func run() { 
    func b() { 
     print("Hello, World!") 
    } 

    func c() { 
     self.someMethod() 
    } 

    func d() { [weak self] 
     self?.someMethod() 
    } 

    a(block: b) // no retain cycle 
    a(block: c) // retain cycle 
    a(block: d) // no retain cycle 
    } 

    func someMethod() { 
    print("Hello, World!") 
    } 
} 
関連する問題