作者:Natasha the Robot,原文鏈接桩盲,原文日期:2015-12-23
譯者:lfb_CD寂纪;校對(duì):numbbbbb;定稿:Cee
有一個(gè)常見(jiàn)的場(chǎng)景:一個(gè) ViewController 控制多個(gè) View 赌结,并且想在 ViewController 中代理 View 的一些邏輯捞蛋。
例如,你有一個(gè) View柬姚,其中包含一個(gè)按鈕(比如在表單中的「注冊(cè)」)拟杉,并且當(dāng)用戶點(diǎn)擊這個(gè)注冊(cè)按鈕時(shí),你希望代理其中的邏輯(比如注冊(cè)驗(yàn)證和調(diào)用 API)量承。
你的代碼應(yīng)該會(huì)是這樣的:
// 代理點(diǎn)擊的協(xié)議
protocol ButtonDelegate {
func onButtonTap(sender: UIButton)
}
class ViewWithTextAndButton: UIView {
// 保存代理搬设,后面使用
var delegate: ButtonDelegate?
func onButtonTap(sender: UIButton) {
// 按鈕被點(diǎn)擊的時(shí)候調(diào)用代理
delegate?.onButtonTap(sender)
}
}
class MyViewController: UIViewController, ButtonDelegate {
let viewWithTextAndButton = ViewWithTextAndButton(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
override func viewDidLoad() {
super.viewDidLoad()
// 給代理賦值
viewWithTextAndButton.delegate = self
view.addSubview(viewWithTextAndButton)
}
// MARK: ButtonDelegate
// 實(shí)現(xiàn)代理邏輯
func onButtonTap(sender: UIButton) {
print("This button was clicked in the subview!")
}
}
但是這里還有一個(gè)很大的問(wèn)題!因?yàn)?View 作為 delegate 對(duì) ViewController 是強(qiáng)引用撕捍,同時(shí) ViewController 對(duì) View 也是強(qiáng)引用拿穴,這就出現(xiàn)了循環(huán)引用。ViewController 引用著 View忧风,并且 View 引用著 ViewController默色,兩者的引用計(jì)數(shù)都不會(huì)變成 0,所以它們都不會(huì)被銷毀狮腿,從而造成內(nèi)存泄露腿宰。
解決辦法就是讓其中一個(gè)對(duì)另一個(gè)保持弱引用!在 Swift 中怎么做呢缘厢?可以添加 class 關(guān)鍵字來(lái)約束協(xié)議吃度,讓它只能被引用類型的數(shù)據(jù)(也就是類)使用:
// 協(xié)議只能被類使用!
protocol ButtonDelegate: class {
func onButtonTap(sender: UIButton)
}
接下來(lái)贴硫,我們可以使得我們的代理被弱引用:
class ViewWithTextAndButton: UIView {
// 注意椿每,現(xiàn)在我們可以使用 weak 關(guān)鍵字!
// 這個(gè)變量只能指向引用類型(UIViewController)
// 并且是弱引用
weak var delegate: ButtonDelegate?
func onButtonTap(sender: UIButton) {
delegate?.onButtonTap(sender)
}
}
就是這樣英遭!
這個(gè)例子很好地說(shuō)明了為什么應(yīng)該使用值類型——值類型可以很好的避免循環(huán)引用拖刃。使用值類型時(shí)值會(huì)被拷貝,所以不會(huì)出現(xiàn)上述的內(nèi)存泄露問(wèn)題贪绘。不過(guò)呢兑牡,我們又不得不和包含大量子類(UIView 和 UIViewController 的關(guān)系)的 Cocoa 框架打交道,所以你需要約束協(xié)議税灌。
本文由 SwiftGG 翻譯組翻譯均函,已經(jīng)獲得作者翻譯授權(quán)亿虽,最新文章請(qǐng)?jiān)L問(wèn) http://swift.gg。