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() } 

我剛剛創建了一個保留週期:視圖控制器 - >按鈕 - >視圖控制器。

然而,斯威夫特讓我做這件事,而不是:

button.wasTapped = buttonWasTapped 

它是安全的這樣做呢? (即,這是否會阻止保留週期?)

回答

3

這仍然會創建保留週期。

一個好辦法去想它是認識到,任何時候你看到:

button.wasTapped = buttonWasTapped 

這只是爲速記:

button.wasTapped = { self.buttonWasTapped() } 

這顯然會創建一個保留週期,明確使用self清楚地表明。

這很混亂,因爲保留週期在第二個版本中很明顯,但不是第一個。

不幸的是,這意味着你將需要堅持到更詳細的(並保留週期避免):

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() 

更新:更多詳情可以fo und here:Function references in Swift and retain cycles

+0

幫助文章:) +1 –

相關問題