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("滚")
}
}