使用回调闭包(块)传回数据

这个主题是 iOS 开发中的一个经典问题,其解决方案与其他已经显示的示例不同。在这个例子中,我将展示另一个日常用途:使用 closure 通过将此页面上的 delegate pattern 示例调整为回调 closure 来传递数据!

这个方法优于 delegate pattern 的一件事是代替在两个不同的地方拆分设置代码(看看这个页面上的代表示例,prepareForSegueuserDidEnterInformation)而不是将它们聚集在一起(仅在 prepareForSegue 中,我将展示它)

从第二视图控制器开始

我们必须弄清楚如何使用回调,然后我们可以编写它,这就是为什么我们从第二个视图控制器开始,因为它是我们使用回调的地方:当我们得到新的文本输入时,我们使用 callback 的参数作为媒介调用我们的回调把数据传回第一个 ViewController,注意我说使用回调的参数,这是非常重要的,新手(因为我)总是忽略这一点,不知道从哪里开始正确编写回调闭包

所以在这种情况下,我们知道我们的回调只带一个参数:text 和它的类型是 String,让我们声明它并使它成为属性,因为我们需要从我们的第一个视图控制器填充

我只评论所有的 delegate 部分,并保留它进行比较

class SecondViewController: UIViewController {

    //weak var delegate: DataEnteredDelegate? = nil
    var callback: ((String?)->())?
    
    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(sender: AnyObject) {
        
        //delegate?.userDidEnterInformation(textField.text!)
        callback?(input.text)
        
        self.navigationController?.popViewControllerAnimated(true)
    }
}

完成第一个视图控制器

所有你需要做的就是传递回调闭包,我们完成了,因为我们已经在第二个视图控制器中设置了封闭将为我们做未来的工作

看看它与 delegate pattern 相比如何缩短我们的代码

//no more DataEnteredDelegate
class FirstViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "showSecondViewController" {
            let secondViewController = segue.destinationViewController as! SecondViewController
            //secondViewController.delegate = self
            secondViewController.callback = { text in self.label.text = text }
        }
    }

    // required method of our custom DataEnteredDelegate protocol
    //func userDidEnterInformation(info: String) {
    //    label.text = info
    //}
}

而在最后,也许有人会因为我们只在一种方式中传递数据(在这种情况下是封闭)而感到困惑,从第一个视图控制器到第二个,没有直接从第二个视图控制器回来,我们怎么能将其视为沟通工具?也许你真的应该运行它并自己证明,我会说它的参数,它是回调闭包的参数传递数据!