闭包的基础我就不说了,网上多如牛毛,现在来介绍几种使用的反向传值的方法。
第一种:
ViewController.swift
@objc func nextController() {
let aaa = AAAViewController()
weak var weakSelf = self
aaa.getBackValue(title: "nextViewController", backgroundColor: UIColor.gray) { (backColor, title) in
weakSelf.view.backgroundColor = backColor
weakSelf.title = title
print("selft.title: \(String(describing: weakSelf.title ))")
}
self.present(aaa, animated: true, completion: nil)
}
AAAViewController.swift
func getBackValue(title: String? = "AAAViewController", backgroundColor: UIColor, lastControllerValue: (_ backgroundColor: UIColor, _ title: String?) -> Void) {
self .title = title
self .view.backgroundColor = backgroundColor
lastControllerValue(UIColor.green, "ViewController")
}
deinit { print("22222222222我释放了无用的内存!!") }
这样就可以把闭包中的值传递过去,但是当 lastControllerValue(UIColor.green, "ViewController") 中的 "ViewController" 换为 self.textField.text 时,在返回值中传递的是空值。因为在 还没跳转到AAAViewController中时,就将值返回去了。所以 lastControllerValue 闭包中的 self.textField.text 为 nil。
第二种:
ViewController.swift 中
@objc func nextController() {
let aaa = AAAViewController()
aaa.changeTitleAndClosure = {
(color: UIColor, title: String) in
self.view.backgroundColor = UIColor.red
self.title = title
}
self.present(aaa, animated: true, completion: nil)
}
AAAViewController.swift
var changeTitleAndClosure:((_ color:UIColor, _ title:String) -> Void)?
@objc func lastController() {
self.dismiss(animated: true, completion: nil)
self.changeTitleAndClosure?(UIColor.green, self.textField.text!)
}
可以将 TextField 中的值传递过去,但是 定义闭包时参数一定不要为可选值,🐔:
var changeTitleAndClosure:((_ color:UIColor?, _ title:String?) -> Void)?
否则,在 ViewController 中的闭包不执行。若非要空,可给它设置一个默认值,🐔:
var changeTitleAndClosure:((_ color:UIColor? = UIColor.orange, _ title:String? = "12345") -> Void)?
第三种:
ViewController.swift
@objc func nextController() {
let aaa = AAAViewController()
aaa.loadData(color: UIColor.red, title: "12345") { (title) in
print("title: \(title)")
}
self.present(aaa, animated: true, completion: nil)
}
AAAViewController.swift
func loadData(color: UIColor, title: String,completion: (_ result:String) -> ()) -> () {
self.view.backgroundColor = color
print("----->title: \(title)")
completion(self.textField.text!)
}
第四种:尾随闭包
增加代码的可读性
ViewController.swift
@objc func nextController() {
let aaa = AAAViewController()
aaa.loadData(color: UIColor.red, title: "12345", completion: {
(title) in
print("~~~~~~~> \(title)")
})
self.present(aaa, animated: true, completion: nil)
}
AAAViewController.swift
func loadData(color: UIColor, title: String,completion: (_ result:String) -> ()) -> () {
self.view.backgroundColor = color
print("----->title: \(title)")
print("耗时操作 \(Thread.current)")
//回调异步获取的结果
completion("武松打虎")
}
第五种: 逃逸闭包
关键字: @escaping
传递给函数的闭包如果不是在函数内调用,而是在函数内用外部变量保存当前的闭包,在合适的时间再进行调用,需要在闭包参数前加入@escaping关键字,否则编译器会报错
ViewController.swift
@objc func nextController() {
let aaa = AAAViewController()
aaa.loadData(color: UIColor.red, title: "12345", completion: {
[unowned self](title) in
print("~~~~~~~> \(title)")
print("weadSelf.view: \(self.view ?? nil)")
})
self.present(aaa, animated: true, completion: nil)
}
AAAViewController.swift
//定义一个闭包属性
var completions : ((_ title: String) -> ())?
@objc func lastController() {
self.dismiss(animated: true, completion: nil)
self.completions?(self.textField.text!)
}
func loadData(color: UIColor, title: String,completion: @escaping (_ result:String) -> ()) -> () {
self.view.backgroundColor = color
print("----->title: \(title)")
self.completions = completion
}
deinit {
print("22222222222我释放了无用的内存!!")
}
第六种: 懒加载
懒加载只会在第一次调用时执行创建对象,后面如果对象被释放了,则不会再次创建。而oc中会再次创建。
1.
lazy var person : Human = {
print("懒加载的定义")
return Human()
}()
//2、懒加载改写为闭包形式
let personFunc = { () -> Human in
print("懒加载 --> 闭包")
return Human()
}
lazy var personDemo : Human =self.personFunc()
//3、懒加载的简单写法
lazy var person2 : Human = Human()
问题: 解决闭包中存在的循环引用
记住这一点:
VC --strong -- 闭包;
闭包- strong -- VC;
就造成了循环引用, Swift 属性的默认 就是强引用:记录了闭包属性,然后在闭包中又使用了self,则产生了循环引用
在ARC中,weak本质是一个观察者模式,一旦对象释放,则把对象置为nil
在MRC中,是通过assign进行若引用的,如果对象释放,assign的指针还是指向该内地地址,会造成野指针
__weak typeof(self) weakSelf = self;
//__unsafe_unretained相当于assign,
__unsafe_unretained typeof(self) weak1Self = self;
方式一:
关键字: weak
注意:weak只能修饰var,不能修饰let,因为如果weak的指针在运行时会被修改,会自动设置为nil
ViewController.swift
@objc func nextController() {
let aaa = AAAViewController()
aaa.loadData(color: UIColor.red, title: "12345", completion: {
(title) in
print("~~~~~~~> \(title)")
print("weadSelf.view: \(self.view ?? nil)")
})
self.present(aaa, animated: true, completion: nil)
}
AAAViewController.swift
// 定义一个闭包属性
var completion : ((_ title: String) -> ())?
func loadData(color: UIColor, title: String,completion: @escaping (_ result:String) -> ()) -> () {
weak var weakSelf = self
weakSelf?.view.backgroundColor = color
print("----->title: \(title)")
completion("武松打虎")
}
deinit {
print("22222222222我释放了无用的内存!!")
}
方式二:
推荐:
[weak self]表示闭包中的self都是若引用
ViewController.swift
@objc func nextController() {
let aaa = AAAViewController()
aaa.loadData(color: UIColor.red, title: "12345", completion: {
[weak self](title) in
print("~~~~~~~> \(title)")
print("weadSelf.view: \(self?.view ?? nil)")
})
self.present(aaa, animated: true, completion: nil)
}
AAAViewController.swift
//定义一个闭包属性
var completion : ((_ title: String) -> ())?
func loadData(color: UIColor, title: String,completion: @escaping (_ result:String) -> ()) -> () {
self.view.backgroundColor = color
print("----->title: \(title)")
completion("武松打虎")
}
deinit {
print("22222222222我释放了无用的内存!!")
}
方式三:
关键字:
[unowned self]:表示闭包中的self为assign,如果self被释放,则指针地址不会被释放,容易导致出现野指针
ViewController.swift
@objc func nextController() {
let aaa = AAAViewController()
aaa.loadData(color: UIColor.red, title: "12345", completion: {
[unowned self](title) in
print("~~~~~~~> \(title)")
print("weadSelf.view: \(self.view ?? nil)")
})
self.present(aaa, animated: true, completion: nil)
}
AAAViewController.swift
//定义一个闭包属性
var completion : ((_ title: String) -> ())?
func loadData(color: UIColor, title: String,completion: @escaping (_ result:String) -> ()) -> () {
self.view.backgroundColor = color
print("----->title: \(title)")
completion("武松打虎")
}
deinit {
print("22222222222我释放了无用的内存!!")
}