1

私は、メモリ管理の点でSwiftのブロックに関数を割り当てるとき(すなわち、保持サイクルを避けたいと思っている)、それが何を意味するのか疑問に思っています。Swiftのブロックに関数を割り当てるときのセマンティクスをキャプチャしますか?

class Button { 
    var wasTapped:() -> Void 
} 

となるように、私はビューコントローラでそれを使用します:

class ViewController { 
    let button: Button 

    func setUpButtonHandler() { 
    button.wasTapped = ... 
    } 

    func buttonWasTapped() { 
    // do something 
    } 
} 

私の質問はbutton.wasTapped = ...の割り当てについてですたとえば、私は次のように定義されたボタンを持つ

を言います。

もちろん、私はそうのようにそれを設定した場合:

button.wasTapped = { self.buttonWasTapped() } 

は私がちょうど保持サイクルを作成:のViewController - >ボタン - >のViewController。

しかし、スウィフトは、私が代わりにこれを行うことができます:

button.wasTapped = buttonWasTapped 

はこれを行うには、それは安全ですか? (つまり、これにより保持サイクルが防止されますか?)

答えて

3

それでも保持サイクルが作成されます。の明示的な使用として、明らかに保持サイクルを作成します

button.wasTapped = { self.buttonWasTapped() } 

button.wasTapped = buttonWasTapped 

それがためだけの速記だ:

それについて考えるための良い方法は、あなたが見ることいつでも実現することですselfが明らかに示しています。

2番目のバージョンでは保持サイクルが明白ですが、最初のサイクルでは明らかではないので、混乱します。

残念ながら、これはあなたがより冗長に固執(および回避サイクルを保持)する必要があります意味:

button.wasTapped = { [weak self] in self?.buttonWasTapped() } 

あなたはこの遊び場で、この動作を確認することができます。

class Button { 
    var wasTapped:() -> Void 

    init() { 
    wasTapped = {} 
    } 
} 

class ViewController { 
    let button: Button 

    func setUpButtonHandler() { 
    //button.wasTapped = { [weak self] in self?.buttonWasTapped() } // no retain cycle 
    //button.wasTapped = { self.buttonWasTapped() } // retain cycle 
    //button.wasTapped = buttonWasTapped // retain cycle 
    } 

    func buttonWasTapped() { 
    print("tapped!") 
    } 

    init() { 
    button = Button() 
    setUpButtonHandler() 
    } 

    deinit { 
    print("deinit") 
    } 
} 

func test() { 
    let vc = ViewController() 
    vc.button.wasTapped() 
} 

test() 

更新:詳細は次のとおりです。ここに:Function references in Swift and retain cycles

+0

便利な投稿:+1 –

関連する問題