-
1.閉包的介紹
- 閉包和OC中的block非常相似
- OC中的block是匿名的函數(shù)
- Swift中的閉包是一個(gè)特殊的函數(shù)
- block和閉包都經(jīng)常用于回調(diào)
- 注意:閉包和block一樣,第一次使用時(shí)可能不習(xí)慣它的語法,可以先按照使用簡單的閉包,隨著學(xué)習(xí)的深入,慢慢掌握其靈活的運(yùn)用方法.
- 閉包和OC中的block非常相似
-
2.閉包的使用
-
1.先回顧一下block的使用
@property(nonatomic,strong) void(^myblock)(); // block 的格式: 返回值類型(^block名稱) (參數(shù)列表) self.myblock = ^(){ NSLog(@"block的打印"); }; self.myblock();
-
2.閉包的基本介紹
/*
* 閉包和oc中的block非常相似
* oc中的block類似于匿名函數(shù)
* 閉包是用來定義函數(shù)
* 作用: block 是用于保存一段代碼,在需要的時(shí)候執(zhí)行
* 閉包也是用于保存一段代碼,在需要的時(shí)候執(zhí)行
* 做一個(gè)耗時(shí)的操作
*//* * 閉包的基本格式: in的含義是用來區(qū)分形參返回值和要執(zhí)行的代碼 * { (形參列表) -> (返回值) in 需要執(zhí)行的代碼 } * */ loadData { print("回調(diào)") } func loadData(request:()->()){ print("執(zhí)行耗時(shí)操作") request() }
-
-
3.閉包的幾種格式
-
1.將閉包通過實(shí)參傳遞給函數(shù)
loadData (request: { print("回調(diào)") }) func loadData(request:()->()){ print("執(zhí)行耗時(shí)操作") request() }
-
-
2.如果閉包是函數(shù)的最后一個(gè)參數(shù),那么閉包可以寫在函數(shù)()的后面
loadData() {print("回調(diào)2") } func loadData(request:()->()){ print("執(zhí)行耗時(shí)操作") request() }
-
3.如果函數(shù)只接受一個(gè)參數(shù),并且這個(gè)參數(shù)是閉包,那么()可以省略
loadData {print("回調(diào)2") } func loadData(request:()->()){ print("執(zhí)行耗時(shí)操作") request() }
4.閉包的返回值和參數(shù)
/*
* 兩個(gè)閉包 創(chuàng)建一個(gè) UIscrollview 上添加button
*
*
*/
let sc1 = createScrollview(buttonCount: { () -> Int in
return 15
}) { (index) -> UIView in
let width1 = 80
let button = UIButton()
button.backgroundColor = UIColor.red
button.frame = CGRect(x:index*width1,y:10,width:width1,height:80)
button.setTitle("標(biāo)題\(index)", for: UIControlState(rawValue: 0))
return button
}
view.addSubview(sc1)
/*
* 要求定義一個(gè)方法來創(chuàng)建UIScrollView,
* 1.并且上面有多個(gè)按鈕,必須通過閉包來告訴該方法
* 2.并且如何創(chuàng)建按鈕也需要閉包來創(chuàng)建
*/
// 5.將scrollview添加到控制器的view上
// 特點(diǎn): 沒有寫self
// swift推薦:能不寫self就不寫self
func createScrollview(buttonCount:()->Int,buttonIndex1: (_ num:Int)->UIView) -> UIScrollView {
// 數(shù)組的數(shù)量
let count = buttonCount()
// 1.創(chuàng)建scrollview
let sc = UIScrollView(frame: CGRect(x:0,y:64,width:414,height:100))
sc.backgroundColor = UIColor.blue
view.addSubview(sc)
// 2.在scrollview上放置button
for i in 0..<count {
/*
let button = UIButton()
button.backgroundColor = UIColor.red
button.frame = CGRect(x:i*width1,y:10,width:width1,height:80)
button.setTitle("標(biāo)題\(i)", for: UIControlState(rawValue: 0))
sc.addSubview(button)
*/
let button = buttonIndex1(i)
sc.contentSize = CGSize(width:CGFloat(count) * button.bounds.width,height:100)
sc.addSubview(button)
}
return sc
}
-
5.循環(huán)引用
import UIKit class ViewController: UIViewController { /* * 在swift中,如果在某個(gè)類中定義一個(gè)屬性,那么這個(gè)屬性必須要初始化,否則就會(huì)報(bào)錯(cuò) * 如果暫時(shí)不想初始化,那么可以在后面寫上一個(gè) ? 也就是可選類型 */ // 注意:這個(gè)是錯(cuò)誤的寫法,當(dāng)前寫法代表閉包的返回值可以是nil //var finsh: ()->()? // 下面是正確的寫法 var finsh: (()->())? override func viewDidLoad() { super.viewDidLoad() weak var weakSelf = self loadata { print("回調(diào)") // 在swift開發(fā)中,能不寫self就不寫self,但是在閉包中必須寫上self // 所以以后看到self基本上都是和閉包有關(guān)系 weakSelf!.view.backgroundColor = UIColor.brown } } func loadata(finsh:()->()) { print("執(zhí)行耗時(shí)操作") finsh() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
**循環(huán)引用解決:以上面的為例
方式一:
- 使用weak,對(duì)當(dāng)前控制器使用弱引用
- 但是因?yàn)閟elf可能有值也可能沒有值,因此weakSelf是一個(gè)可選類型,在真正使用時(shí)可以對(duì)其強(qiáng)制解包(該處強(qiáng)制解包沒有問題,因?yàn)榭刂破饕欢ù嬖?否則無法調(diào)用所在函數(shù))
weak var weakSelf = self
loadata {
print("回調(diào)")
// 在swift開發(fā)中,能不寫self就不寫self,但是在閉包中必須寫上self
// 所以以后看到self基本上都是和閉包有關(guān)系
weakSelf!.view.backgroundColor = UIColor.brown
}
}
方式二:
- 和方案一類型,只是書寫方式更加簡單
- 可以寫在閉包中,并且在閉包中用到的self都是弱引用
loadata { [weak self] () -> () in
print("回調(diào)")
// 在swift開發(fā)中,能不寫self就不寫self,但是在閉包中必須寫上self
// 所以以后看到self基本上都是和閉包有關(guān)系
self!.view.backgroundColor = UIColor.brown
}
}
方式三:
- 使用關(guān)鍵字unowned
- 從行為上來說 unowned 更像OC中的 unsafe_unretained
- unowned 表示:即使它原來引用的對(duì)象被釋放了,仍然會(huì)保持對(duì)被已經(jīng)釋放了的對(duì)象的一個(gè) "無效的" 引用,它不能是 Optional 值,也不會(huì)被指向 nil
loadata { [unowned self] () -> () in
print("回調(diào)")
// 在swift開發(fā)中,能不寫self就不寫self,但是在閉包中必須寫上self
// 所以以后看到self基本上都是和閉包有關(guān)系
self.view.backgroundColor = UIColor.brown
}
}