Swift:委托和协议

与Swift在一起待了将近10天,即将到来的项目。 一切工作都很好,直到出现了“委托和协议”之类的内容,才真正使我难受。 这就是为什么此注释旨在揭示后续回调的基本原理的原因。 由于本文仅供个人使用和注意,因此本文内容非常密集,请随时向我询问详细说明。

1.什么是委托和协议? 简而言之,这是iOS应用程序开发中的一种设计模式,用于处理从一个视图控制器到另一个视图控制器的数据传递。 期。

2.为什么我们在地球上需要委托和协议? 这是一个非常大的问题。 让我们首先回顾一下在Swift中传递数据的传统方法,以掌握全局。 为第一个视图控制器和第二个视图控制器设置两个设置:

第一视图控制器:

  // ViewController.swift 
// Segues
//
//由VuNguyen创建于2018/11/17。
//版权所有©2018 VuNguyen。 版权所有。
//
导入UIKit
ViewController :UIViewController {var textFromSecondView:字符串?
@IBOutlet弱var firstLabel:UILabel!
@IBOutlet var textField:UITextView!
覆盖func viewDidLoad(){
super.viewDidLoad()
//加载视图后进行其他任何设置,通常是从笔尖进行。
firstLabel.text = textFromSecondView
}
@IBAction func sendDataForward(_ sender:UIButton){
performSegue(withIdentifier:“ goToSecondScreen”,发送者:self)
}
覆盖func prepare(用于segue:UIStoryboardSegue,发送者:Any?){如果segue.identifier ==“ goToSecondScreen” {
让destinationVC = segue.destination作为! SecondViewController
destinationVC.textFromFirstView = textField.text!
}
}
}

第二个视图控制器:

  // 
// SecondViewController.swift
// Segues
//
//由VuNguyen创建于2018/11/17。
//版权所有©2018 VuNguyen。 版权所有。
//
导入UIKit
class SecondViewController :UIViewController {var textFromFirstView:字符串?
@IBOutlet弱var secondLabel:UILabel!
@IBOutlet弱var textField:UITextView!
覆盖func viewDidLoad(){
super.viewDidLoad()
//加载视图后进行其他任何设置,通常是从笔尖进行。
secondLabel.text = textFromFirstView}
@IBAction func sendDataBackward(_ sender:UIButton){
performSegue(withIdentifier:“ goToFirstScreen”,发送者:self)}
覆盖func prepare(用于segue:UIStoryboardSegue,发件人:任意?){
如果segue.identifier ==“ goToFirstScreen” {
让destinationVC = segue.destination作为! ViewController
destinationVC.textFromSecondView = textField.text!
}
}
}

您可以尝试通过来回传递数据来尝试一下,一切似乎都很好。 现在这是有趣的部分,让我们通过创建ChangeColor按钮来更改第一个视图的背景:

将数据转发到第二个视图:

现在向后发送数据:

布姆! 纯蓝色背景在哪里? 去哪了 发生了什么?

关键在于segue.destination 。 这意味着每次我们向前或向后传递数据时,都会创建每个视图的一个NEW实例(新对象) 。 试想一下,当我们第一次进入第一个屏幕时,默认的背景颜色是灰色,对吗? 那是第一个视图控制器的第一个对象(原始的第一个视图对象版本)。 然后我们点击“ ChangeColor”按钮,它将第一个对象的背景颜色属性的属性更改为“ blue”。 换句话说,第一对象被更新(改变的第一视图对象版本)。

在传递前向数据时创建第二个视图对象。 现在向后看, 将使用默认的背景颜色属性重新创建另一个第一个视图对象,该属性为灰色,与原始的第一个视图对象相似。

因此,最大的问题是我们如何保持第一个视图对象不变? 如何在不创建新视图对象的情况下重用第一个视图对象?

那是Delegate和Protocol进行营救的时候 。 让我们回顾一下概念的定义:

代表 是由上司/上级委派或授予做某事的权利的事物/人。 协议 是代表必须遵守的合同。

我的Swift定义:

一个对象( Delegate )将遵守 另一个对象(老板)建立 的规则( Protocol )。 在我们的例子中,第二个视图对象(老板)现在将拥有一个委托属性,即第一个对象,而第一个对象将遵守由第二个对象设置的规则(协议)。

这样,在将数据发送回时,我们可以将目标定位为正确的第一个对象,即带有蓝色背景的更改版本,而无需创建新实例。 足够多的讨论,这是我们的代理协议修改版本:

第一视图控制器:

  // 
// ViewController.swift
// Segues
//
//由VuNguyen创建于2018/11/17。
//版权所有©2018 VuNguyen。 版权所有。
//
导入UIKit
ViewController :UIViewController, SecondViewContract {
var textFromSecondView:字符串吗? @IBOutlet弱var firstLabel:UILabel!
@IBOutlet var textField:UITextView!
覆盖func viewDidLoad(){
super.viewDidLoad()
//加载视图后进行其他任何设置,通常是从笔尖进行。
如果让textFromSecondView = textFromSecondView {
firstLabel.text = textFromSecondView
}
} @IBAction func changeColorPressed(_ sender:UIButton){
view.backgroundColor = UIColor.blue
} @IBAction func sendDataForward(_ sender:UIButton){
performSegue(withIdentifier:“ goToSecondScreen”,发送者:self)
}覆盖f​​unc prepare(用于segue:UIStoryboardSegue,发件人:任意?){
如果segue.identifier ==“ goToSecondScreen” {
让destinationVC = segue.destination作为! SecondViewController
destinationVC.textFromFirstView = textField.text!
destinationVC.delegate =自我
}
} func changeFirstLabel(input:String){
firstLabel.text =输入
}
}

第二个视图控制器:

  // 
// SecondViewController.swift
// Segues
//
//由VuNguyen创建于2018/11/17。
//版权所有©2018 VuNguyen。 版权所有。
//
导入UIKit 协议SecondViewContract {
func changeFirstLabel(输入:字符串)
}SecondViewController :UIViewController {var textFromFirstView:字符串?
var委托:SecondViewContract? @IBOutlet弱var secondLabel:UILabel!
@IBOutlet弱var textField:UITextView!
覆盖func viewDidLoad(){
super.viewDidLoad()
//加载视图后进行其他任何设置,通常是从笔尖进行。
如果让textFromFirstView = textFromFirstView {
secondLabel.text = textFromFirstView
}
} @IBAction func sendDataBackward(_ sender:UIButton){
委托?.changeFirstLabel(输入:textField.text!)
self.dismiss(动画:true,完成:nil)
}
}

现在让我重新开始。 现在,SecondViewController是设置规则协议SecondViewContract的老板(如果需要,请委托人)。 具体来说,委托人必须遵守规则“ changeFirstLabel”。 该协议与SecondViewController类完全分开,您可以随意放入一个不同的文件中。 这是魔术的工作原理:

  • 步骤1 :当iPhone加载我们的第一个视图时,它将创建ViewController的实例,这是第一个视图对象。
  • 步骤2 :在segue.destination行创建了SecondViewController的新实例。
  • 步骤3 :照常将新实例的textFromFirstView属性设置为用户文本字段输入
  • 步骤4 :将第一个视图对象作为委托附加到新创建的第二个视图对象
  • 步骤5 :将数据转发到第二个视图控制器。 实际上,数据已在我们刚刚提到的Step2中发送到实例。
  • 步骤6 :由于步骤2中的实例现在拥有第一个视图对象作为委托,因此它可以将数据发送回该第一个视图对象,而无需创建任何新的ViewController实例。 因此,在SecondViewController中,我们已经删除了segue.destination并调用了委托?.changeFirstLabel(textField.text!),这意味着“ 嘿,第一个对象,请更改您的第一个标签,并保持颜色背景不变。您在此处发送了数据 ”。 这就是为什么当我们返回时,彩色背景将是转发数据之前的背景。

这是最后的节目:

转发:

向后:

哇! 这就是代表和协议的全部内容。