????閉包的基礎我就不說了同辣,網上多如牛毛,現在來介紹幾種使用的反向傳值的方法谷丸。
第一種:
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 中的閉包不執(zhí)行你雌。若非要空,可給它設置一個默認值二汛,??:
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我釋放了無用的內存Cフ弧!")
? ? }
第六種: 懶加載
懶加載只會在第一次調用時執(zhí)行創(chuàng)建對象婿着,后面如果對象被釋放了授瘦,則不會再次創(chuàng)建。而oc中會再次創(chuàng)建竟宋。
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() ?
問題: 解決閉包中存在的循環(huán)引用
記住這一點:
VC --strong -- 閉包;
閉包- strong -- VC丘侠;
就造成了循環(huán)引用徒欣,?Swift 屬性的默認 就是強引用:記錄了閉包屬性,然后在閉包中又使用了self蜗字,則產生了循環(huán)引用?
在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我釋放了無用的內存Dⅰ此虑!")
? ? }