Block
- Block格式:
- 形参:
返回值类型(^Block名称)(形参列表)
- 值:
^(形参列表){
// 逻辑代码
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self loadData:^{ NSLog(@"%@", [NSThread currentThread]); NSLog(@"回到主线程更新UI"); }]; } - (void)loadData:(void(^)())myBlock { // 1.异步获取数据 dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"%@", [NSThread currentThread]); NSLog(@"异步获取数据"); // 2.回到主线程更新UI dispatch_async(dispatch_get_main_queue(), ^{ myBlock(); }); }); }
闭包
- 闭包和OC中的Block很像
- OC中的Block类似于匿名函数
- Swift中的闭包就是一个特殊的函数
- Block一般用于回调,异步准备数据,然后通过Block回调更新UI
闭包的格式:
- (形参列表) -> 返回值
技巧:
- 闭包类型,先写上 () -> () 然后再根据具体情况进行定义
值:
- in的作用就是用于分隔逻辑代码和描述
{ (形参列表) -> 返回值类型 in //逻辑代码 }
闭包的简写
- 如果没有返回值也没有参数,那么in和in之前的代码可以删除
- 如果闭包是形参列表的最后一个参数,那么可以把闭包写到()的后面
- 如果函数只有一个形参,并且这个形参是一个闭包,那么()可以不写
- loadData({ () -> () in ***code****})
- loadData( { ***code*** } )
- loadData (){ ***code*** } //称为尾随闭包
- loadData { ***code*** } // 称为尾随闭包 推荐这种写法
// loadData ({ () -> () in // print(NSThread.currentThread()) // print("回到主线程更新UI") // }) // loadData ({ // print(NSThread.currentThread()) // print("回到主线程更新UI") // }) // 以下两种写法, 我们称之为尾随闭包 // loadData (){ // print(NSThread.currentThread()) // print("回到主线程更新UI") // } // 开发中建议写下面这一种写法 loadData { print(NSThread.currentThread()) print("回到主线程更新UI") } } func loadData(myBlock: ()->()) { dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in print(NSThread.currentThread()) print("异步准备数据") dispatch_async(dispatch_get_main_queue(), { () -> Void in myBlock() }) } }
闭包的循环引用
- OC中Block的循环引用: __weak typeof(self) weakSelf = self ;
- Swift中闭包的循环引用的解决方法: weak var weakSelf = self //因为变量是weak的,随时有可能被释放,所以系统推导是可选类型
class ViewController: UIViewController { // 报错的原因: Swift规定一个对象中的属性必须在对象初始化时全部初始化 // 如果没有在初始化时给所有的属性赋值, 那么就会报错 // 要想不报错, 那么可以让属性变成可选的 // 注意: 错误写法()->()? , 这中写法代表闭包的返回值是可选的, 而不是闭包是可选的 // 可选类型的值, 如果没有初始化, 那么默认值就是nil var finished: (()->())? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. view.backgroundColor = UIColor.purpleColor() } override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { /* // 方法1 // OC中: __weak typeof(self) weakSelf = self; // 因为变量是weak的, 随时有可能被释放, 所以系统推导是可选类型 // Swift中: weak var weakSelf = self weak var weakSelf = self loadData { () -> () in print(NSThread.currentThread()) print("回到主线程更新UI") weakSelf!.view.backgroundColor = UIColor.redColor() //weakSelf 强制解包 } */ /* //方法2 loadData { [weak self]() -> () in //[weak self] print(NSThread.currentThread()) print("回到主线程更新UI") self!.view.backgroundColor = UIColor.redColor() //self 强制解包 } */ // 方法3 开发中推荐这样写 // Swift中的weak对应OC中的__weak, 如果对象释放了, 那么会自动将变量赋值为nil // Swift中的unowned对应OC中的__unsafe_unretained, 如果对象释放了, 不会将变量赋值为nil, 如果对象释放了再继续访问会出现野指针错误 loadData { [unowned self] () -> () in //[unownes self] print(NSThread.currentThread()) print("回到主线程更新UI") self.view.backgroundColor = UIColor.redColor() } } func loadData(myBlock: ()->()) { dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in print(NSThread.currentThread()) print("异步准备数据") dispatch_async(dispatch_get_main_queue(), { () -> Void in self.finished = myBlock myBlock() }) } } // OC : dealloc // Swift: deinit deinit { // 只要对象释放就会调用这个方法 print("滚") } }