一.闭包的介绍
闭包和OC中的block非常相似
- OC中的block是匿名的函数
- Swift中的闭包是一个特殊的函数
- block和闭包都经常用于回调
二.block的用法回顾
1.block写法总结
类型:
返回值(^block的名称)(block的参数)
值:
^(参数列表) {
// 执行的代码
}
int (^sumOfNumbers)(int a, int b) = ^(int a, int b) {
return a + b;
};
2.block实现两个界面之间的传值
①在后面控制器的 .h文件 中声明block
// 一会要传的值为NSString类型
typedef void (^newBlock)(NSString *);
@interface NewViewController : UIViewController
// 声明block属性
@property (nonatomic, copy) newBlock block;
②在后面控制器的 .m文件 中设置block
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:YES];
if (self.block != nil) {
self.block(@"呵呵");
}
}
③在前面控制器的 .m文件 中接收传来的值
NewViewController *newVC = [[NewViewController alloc] init];
// 接收block传来的值
__weak ViewController *weakSelf = self;
在 Block 中引用self,也就是 ViewController ,而 ViewController 创建并引用了 NewViewController,而NewViewController引用 block,此时就形成了一个循环引用,所以要用__weak修饰。
newVC.block = ^(NSString *str){
NSLog(@"%@", str);
};
三.闭包的用法
1.闭包的写法总结
类型:(形参列表)->(返回值)
技巧:初学者定义闭包类型,直接写()->().再填充参数和返回值
值:
{
(形参) -> 返回值类型 in
// 执行代码
}
let b = { (parm : Int) -> (Int) in
print(parm)
……
}
//调用
b(100)
2.闭包的简写
如果闭包没有参数,没有返回值,in和in之前的内容可以省略.
httpTool.loadRequest({
print("回到主线程", NSThread.currentThread());
})
3.尾随闭包写法
- 如果闭包是函数的最后一个参数,则可以将闭包写在()后面
- 如果函数只有一个参数,并且这个参数是闭包,那么()可以不写
httpTool.loadRequest() {
print("回到主线程", NSThread.currentThread());
}
// 开发中建议该写法
httpTool.loadRequest {
print("回到主线程", NSThread.currentThread());
}
4.闭包的使用例子:延迟回调
//[weak self]:解决驯化引用导致的内存泄露
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
delayMethod {[weak self] (re) ->() in
print("$$$$$$$$$$$$$$$$$:\(re)%%%%%%%%%%%\(String(describing: self))")
}
delayMethod(comletion: {[weak self] (re)->() in
print("********:\(re)*************\(String(describing: self))")
})
}
//@escaping:逃逸闭包。它的定义非常简单而且易于理解。如果一个闭包被作为一个参数传递给一个函数,并且在函数return之后才被唤起执行,那么这个闭包是逃逸闭包。
func delayMethod(comletion: @escaping (_ results: String,_ resultss:String) -> ()) ->(){
//开启一个全局异步子线程
DispatchQueue.global().async {
Thread.sleep(forTimeInterval: 2.0)
//回调到主线程
DispatchQueue.main.async(execute: {
print("主线程更新 UI \(Thread.current)")
comletion("qwertyui","asdf")
})
}
}
运行结果:
5.闭包的使用例子:两个界面之间的回调
//实现B界面要传值给上个界面A
//首先在B界面声明闭包
typealias lewisCloser = (_ paramOne : String? ) -> ()
//定义个变量 类型就是上面声明的闭包
var customeCloser: lewisCloser?
//点击事件 回跳到A界面 实现传值
@IBAction func tap(_ sender: Any) {
if(customeCloser != nil) {
customeCloser!("qq")
}
self.dismiss(animated: true, completion: nil)
}
//在A界面接受B界面传过来的值
@IBAction func tap(_ sender: UIButton) {
let vc = NewViewController()
vc.customeCloser = {(cusValue) -> () in
self.slipTap.titleLabel!.text! = cusValue!;
print("^^^^^^^^^^^^^^^^^^^^^:\(cusValue!)")
}
self.present(vc, animated: true, completion: nil)
}
That's all,THX! 欢迎小伙伴的交流评论!