Swift3.0 函数闭包与 Block
2017-06-08 本文已影响99人
PetitBread
最近新接手了一个Swift项目,花点时间做点小结,以做记录
我的博客链接
Swift中定义一个基本函数
//定义一个函数,接收一个字符串,返回一个String类型的值
func test(name:String) -> String {
return ("输出了\(name)")
}
//通用形式
func name(parameters) -> return type {
function body
}
Swift 中基本的闭包函数与OC中Block的相似点
904629-95160b50313b3606.png带参闭包
void (^test) (NSString *)=^(NSString *name){
NSLog(@"%@",name);
};
test(@"测试");
//对应到swift的带参闭包
let test={(_ name:String)->() in
// in 后面就是回调之后处理的函数 ,相当于是Block之后的{ }
print(name)
}
test("测试")
//通用形式
{
(parameters) -> returnType in
code
}
这里下划线 _ 的作用用来忽略外部參数名,具体可以参考这篇文章
带参函数定义
-(void)loadData:( void(^)(void) )completetion
{
completetion();
}
func loadData(completetion: ()->()) -> () {
completetion()
}
//样式 func: ()->()
举栗子,网络数据获取
- OC
//OC中Block传值
-(void)loadData:( void(^)(NSArray *) )completetion
{
//这里暂时先忽略掉线程,简单处理,重点在swift闭包
NSLog(@"耗时操作");
sleep(2);//模拟网络请求
NSArray *arr=@[@"1",@"2"];
NSLog(@"主线程回调");
completetion(arr); //返回获得的数据
}
调用:
[self loadData:^(NSArray *callBack){
NSLog(@"%@,%@",callBack[0],callBack[1]);
}];
输出:
2017-03-22 18:48:45.273 tessst[3642:187462] 耗时操作
2017-03-22 18:48:47.345 tessst[3642:187462] 主线程更新
2017-03-22 18:48:47.346 tessst[3642:187462] 1,2
- Swift
//swift中闭包传值
func loadDate(completion: @escaping (_ result : [String])->()) -> () {
//这里有一个很重要的参数 @escaping,逃逸闭包
//简单来说就是 闭包在这个函数结束前内被调用,就是非逃逸闭包,调用的地方超过了这函数的范围,叫逃逸闭包
//一般网络请求都是请求后一段时间这个闭包才执行,所以都是逃逸闭包。
// 在Swift3.0中所有的闭包都默认为非逃逸闭包,所以需要用@escaping来修饰
DispatchQueue.global().async {
print("耗时操作\(Thread.current)")
Thread.sleep(forTimeInterval: 2)
let json=["1","2"]
DispatchQueue.main.async {
print("主线程更新\(Thread.current)")
completion(json)
//函数在执行完后俩秒,主线程才回调数据,超过了函数的范围,这里就是属于逃逸闭包,如果不用@escaping,编译器是编译不过的
}
}
}
主函数调用loadDate:
loadDate { (callBack) in
print("\(callBack)")
}
输出值
耗时操作<NSThread: 0x608000069140>{number = 1, name = main}
主线程更新<NSThread: 0x608000069140>{number = 1, name = main}
1,2
循环引用
- 在Block中经常会有循环引用的情况,Swift闭包中也一样,常用的解决方式有俩种
//第一种
weak var weakwelf=self
//套用oc的方式(__weak typedef(weakself)=self).
//这里要注意,不能用 let ,因为self可能会释放指向nil,相当于是一个可变值
//调可选项发送消息的时候 用 ? 解包 不用 !
pringt("weakself ?.view") 不用" weakself!.view"
//因为强制解包一旦weakself=nil时会崩溃
//第二种,在调用时候
//[weak self]标识在{}中所有的self都是弱引用
loadDate { [weak self] in
print(self?.view)
}
尾随闭包
func someFunctionThatTakesAClosure(closure: () -> ()) {
// 函数体部分
}
// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure({
// 闭包主体部分
})
// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
}