iOS:如何用 Swift 實現弱代理

jopen 8年前發布 | 12K 次閱讀 Swift Apple Swift開發

作者:Natasha the Robot, 原文鏈接 ,原文日期:2015-12-23

譯者:lfb_CD;校對: numbbbbb ;定稿: Cee

</div>

有一個常見的場景:一個 ViewController 控制多個 View ,并且想在 ViewController 中代理 View 的一些邏輯。

例如,你有一個 View,其中包含一個按鈕(比如在表單中的「注冊」),并且當用戶點擊這個注冊按鈕時,你希望代理其中的邏輯(比如注冊驗證和調用 API)。

你的代碼應該會是這樣的:

// 代理點擊的協議
protocol ButtonDelegate {
    func onButtonTap(sender: UIButton)
}

class ViewWithTextAndButton: UIView {

    // 保存代理,后面使用
    var delegate: ButtonDelegate?

    func onButtonTap(sender: UIButton) {
        // 按鈕被點擊的時候調用代理
        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
    // 實現代理邏輯
    func onButtonTap(sender: UIButton) {
        print("This button was clicked in the subview!")
    }

}

</div>

但是這里還有一個很大的問題!因為 View 作為 delegate 對 ViewController 是強引用,同時 ViewController 對 View 也是強引用,這就出現了循環引用。ViewController 引用著 View,并且 View 引用著 ViewController,兩者的引用計數都不會變成 0,所以它們都不會被銷毀,從而造成內存泄露。

解決辦法就是讓其中一個對另一個保持弱引用!在 Swift 中怎么做呢?可以添加 class 關鍵字來約束協議,讓它只能被引用類型的數據(也就是類)使用:

// 協議只能被類使用!
protocol ButtonDelegate: class {
    func onButtonTap(sender: UIButton)
}

</div>

接下來,我們可以使得我們的代理被弱引用:

class ViewWithTextAndButton: UIView {

    // 注意,現在我們可以使用 weak 關鍵字!
    // 這個變量只能指向引用類型(UIViewController)
    // 并且是弱引用
    weak var delegate: ButtonDelegate?

    func onButtonTap(sender: UIButton) {
        delegate?.onButtonTap(sender)
    }
}

</div>

就是這樣!

這個例子很好地說明了為什么應該使用值類型——值類型可以很好的避免循環引用。使用值類型時值會被拷貝,所以不會出現上述的內存泄露問題。不過呢,我們又不得不和包含大量子類(UIView 和 UIViewController 的關系)的 Cocoa 框架打交道,所以你需要約束協議。

本文由 SwiftGG 翻譯組翻譯,已經獲得作者翻譯授權,最新文章請訪問http://swift.gg。

</div> </div>

來自: http://swift.gg/2016/01/19/ios-weak-delegates-swift/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!