繁体   English   中英

嵌套回调强参考周期

[英]Nested callback strong reference cycle

@IBAction func sendSweet(sender: UIBarButtonItem) {

    var inputTextField: UITextField?
    let alert = UIAlertController(title: "New sweet", message: "Enter a sweet", preferredStyle: .alert)
    alert.addTextField { (textField: UITextField) in
        textField.placeholder = "Your sweet"
        inputTextField = textField
    }

    let sendAction = UIAlertAction(title: "Send", style: .default, handler: {
        [weak self] (alertAction: UIAlertAction) in
        guard let strongSelf = self else { return }

        if inputTextField?.text != "" {
            let newSweet = CKRecord(recordType: "Sweet")
            newSweet["content"] = inputTextField?.text as CKRecordValue?

            let publicData = CKContainer.default().publicCloudDatabase
            publicData.save(newSweet, completionHandler: {
                (record: CKRecord?, error: Error?) in

                if error == nil {
                    // we want ui code to dispatch asychronously in main thread
                    DispatchQueue.main.async {
                        strongSelf.tableView.beginUpdates()
                        strongSelf.sweets.insert(newSweet, at: 0)
                        let indexPath = IndexPath(row: 0, section: 0)
                        strongSelf.tableView.insertRows(at: [indexPath], with: .top)
                        strongSelf.tableView.endUpdates()
                    }
                } else {
                    if let error = error {
                        print(error.localizedDescription)
                        return
                    }
                }
            })
        }
    })

    alert.addAction(sendAction)
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    present(alert, animated: true, completion: nil)

}

我有这个回调地狱,我想知道

  1. [weak self]guard let strongSelf在回调地狱的最顶端guard let strongSelf阻止了强引用循环通过GCD的异步回调全部消失。 我在这里读了另一篇文章,也从书中读到,说如果我在回调内引用的对象可以成功deinit ,则意味着没有强大的引用周期是一个好兆头,是否仍然如此?

  2. 如何防止这种回调地狱,您能带我去一些我所错过的阅读材料或主题吗? 像JavaScript的promise链语法一样吗?

据我所知,没有保持周期,因此不需要削弱self 当然,您可以在每一个环节都做到这一点,以防身。

因为实例( self )没有引用任何闭包,所以没有保留周期。 特别是对于sendAction ,因为sendActionsendSweet函数内部声明。

class MyView: UIView {
    let str = "some variable to have somsthing to use self with"

    func foo() {
        let ba = {
            // no problem. The instance of MyView (self) does not hold a (strong) reference to ba
            self.str.trimmingCharacters(in: CharacterSet.alphanumerics)
        }

        ba()
    }
}

如果将let sendAction = ...作为实例的属性let sendAction = ...函数,则会有一个参考循环。 在这种情况下,实例( self )对sendAction的引用很强, sendAction闭包对实例( self )的引用很强:

自我<-> {自我。 ...}又名sendAction

class MyView: UIView {
    let str = "asd"
    // Problem. 
    // The instance of MyView (self) does hold a (strong) reference to ba ...
    let ba: () -> Void 

    override init(frame: CGRect) {
        super.init(frame: frame)
        ba = {     
            // ... while ba holds a strong reference to the instance (self)           
            self.str.trimmingCharacters(in: CharacterSet.alphanumerics)
        }
    }

    func foo() {
        ba()
    }
}

在这种情况下,您必须像以前一样通过weak封闭中的self来打破循环。


如何防止这种回调地狱,您能带我读一些材料吗?

签出DispatchGroup

Apple文档

找到了解决我的问题2的好方法

https://github.com/duemunk/Async

示例片段:

Async.userInitiated {
    return 10
}.background {
    return "Score: \($0)"
}.main {
    label.text = $0
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM