美文网首页swiftiOS学习iOS开发
Swift3.0 函数闭包与 Block

Swift3.0 函数闭包与 Block

作者: PetitBread | 来源:发表于2017-06-08 17:56 被阅读99次

    最近新接手了一个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() {
            // 闭包主体部分
        }
    

    相关文章

      网友评论

        本文标题:Swift3.0 函数闭包与 Block

        本文链接:https://www.haomeiwen.com/subject/mhytqxtx.html