一、导语:
- 最近在研究Swift中返向传值,其中遇到了一些问题,想把自己学习的经过记录下来,希望可以帮助那些需要学习闭包传值和代理传值的程序猿们。来吧!
- 需求:
- 三个界面:先创建三个视图控制器:A(ViewController)、B(SecondViewController)、C(ThirdViewController);
- 改变A界面的title和背景色(闭包传值):从A界面 -> B界面:只是推进B界面,什么都不用做,反过来从B -> A界面闭包传值,传值string、color分别改变A界面的title和背景色;
- 改变B界面的title和背景色(代理传值)从B界面 -> C界面:只是推进C界面,什么都不用做,反过来从C -> B界面代理传值,传值string、color分别改变B界面的title和背景色;
- 效果gif动画:
二、要了解什么是闭包?如何定义闭包?
- 闭包:闭包是功能性自包含模块,可以在代码中被传递和使用。 Swift 中的闭包与C和Objective-C中的blocks比较相似,有关闭包的更多知识请点击Swift中文网http://c.biancheng.net/cpp/html/2285.html。
- 定义闭包:
- 定义闭包无须func关键字,无须指定函数名;
- 定义闭包需要额外使用in关键字;
- 定义闭包的第一个花括号要移到形参列表的圆括号之前。
- 闭包表达式: { (形参列表) -> 返回值类型 in
//零条到多条可执行性语句
}
三、Swift中闭包传值:
- 在B界面中要做以下工作:
//1.声明闭包(定义闭包类型):关键字typealias类似于OC中typedef
typealias sendValueClosure = (_ string:String, _ textColor:UIColor) -> Void
//2.声明一个闭包变量:
var myClosure : sendValueClosure!
//3.创建闭包方法(传值):
func buttonClick()->Void{//此方法为点击B界面中的Button返回到A界面
if myClosure != nil {
myClosure("你好!FirstVC_闭包传值!",UIColor(red:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)),green:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)), blue:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)), alpha:1))
}
_ = self.navigationController?.popViewController(animated: true)
}
也可以这样写:
//1.声明闭包(定义闭包类型):关键字typealias类似于OC中
typedef typealias sendValueClosure = (_ string:String, _ textColor:UIColor) -> Void
//2.声明一个闭包变量:
var myClosure : sendValueClosure!
//3.创建闭包方法(传值):
func buttonClick()->Void{//此方法为点击B界面中的Button返回到A界面
if myClosure != nil {
myClosure("你好!FirstVC_闭包传值!", UIColor(red:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)), green:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)), blue:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)), alpha:1))
}
_ = self.navigationController?.popViewController(animated: true) }
func initClosure(closure:sendValueClosure?) -> Void {
myClosure = closure
}
- 在A界面中要做以下工作:
func buttonClick() -> Void {//此方法是推进B界面并 let
secondVC = SecondViewController()//初始化B界面
secondVC.myClosure = {//B界面的闭包变量赋值
(string:String,color:UIColor) -> Void in self.view.backgroundColor = color self.title = string
}
self.navigationController?.pushViewController(secondVC, animated: true)
}
代码也可以这样写:
func buttonClick() -> Void {//此方法是推进B界面并 let
secondVC = SecondViewController()//初始化B界面
secondVC.initClosure(closure:
someFunctionThatTakesAClosure)
self.navigationController?.pushViewController(secondVC, animated: true)
}
func someFunctionThatTakesAClosure(string:String,textColor:UIColor) -> Void {
self.view.backgroundColor = textColor self.title = string
}
四、代理传值:
- Swift中的代理传值和OC中的代理传值很一样,只是语言不同。谁有需求谁就是委托方,而另一方则是代理方即被委托的对象。
- C界面(代理方)中要做以下事情:
//1.制定协议和方法并遵守NSObjectProtocol protocol
ThirdViewControllerDelegate:NSObjectProtocol {
func passValueToSecondVC(_ string:String, color:UIColor)
}
//2.点击此处返回B界面
@IBAction func popToSecondVC(_ sender: Any) {
if delegate != nil{
delegate.passValueToSecondVC("你好!SecondVC_代理传值!", color: UIColor(red:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)), green:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)), blue:CGFloat(CGFloat(arc4random())/CGFloat(RAND_MAX)), alpha:1))
}
_ = self.navigationController?.popViewController(animated: true)
}
- B界面(委托方)要做以下事情:
//1.遵守协议ThirdViewControllerDelegate class SecondViewController: UIViewController,ThirdViewControllerDelegate
//2.设置代理
func button_0Click() -> Void {
let thirdVC = ThirdViewController()
thirdVC.delegate = self
self.navigationController?.pushViewController(thirdVC, animated: true)
}
//3.执行代理方法
func passValueToSecondVC(_ string: String, color: UIColor) {
self.title = string
self.view.backgroundColor = color
}