ios - 嵌套回调强引用循环

标签 ios swift multithreading swift3 grand-central-dispatch

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

}

我有这个回调 hell ,我想知道

  1. [weak self]guard let strongSelf 是否在回调 hell 的最顶端阻止了整个 GCD 异步回调的强引用循环。我在这里读了一些其他的帖子,也是一本书中的一篇,说如果我在回调中引用的对象可以 deinit 成功,这意味着没有强引用循环的好兆头,它仍然是真的吗?

  2. 如何防止这种回调 hell ,你能引导我阅读一些我错过的阅读 Material 或主题吗?有什么类似 javascript 的 promise 链接语法吗?

最佳答案

据我所知,没有保留周期,因此没有必要弱化 self。您当然可以在每个街区都这样做以进行防守。

没有保留周期,因为实例 (self) 没有引用任何闭包。特别是 sendAction,因为 sendAction 是在 sendSweet 函数内部声明的。

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 = ... 作为实例的属性移动到函数之外,您将拥有一个引用循环。在这种情况下,实例 (self) 将对 sendAction 有强引用,而 sendAction 闭包将对实例 ( self ):

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

在这种情况下,您必须像您所做的那样,通过在闭包中weakifying self 来打破循环。


How to prevent this kind of callback hell, can you lead me to some reading material

checkout DispatchGroup

( Apple Documentation )

关于ios - 嵌套回调强引用循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41073040/

相关文章:

objective-c - 您可以为 UIStepper 对象设置默认/当前值吗?

ios - Swift iOS 中的 Facebook 相册访问

ios - 如何在 React Native 中支持 WebP 图片?

objective-c - 使用 IBAction 而不是 touchesBegan :

Swift:二元运算符 '==' 不能应用于 "protocol"类型的操作数

ios - 在 Swift 3 中使用默认初始值设定项更改可选属性值

iOS/swift 4 : How to copy a folder containing several folders containing files without removing the files and folders existing destination?

c - CUDA并行计算是如何工作的?

java - Rox 教程中的 Java NIOServer 真的安全吗?

java - 如何在新线程中创建数组的副本