美文网首页Swift学习
swift-基础-闭包

swift-基础-闭包

作者: 埃林的奶酪 | 来源:发表于2016-08-15 11:56 被阅读46次
    • 闭包和OC中的Block差不多,也是保存一段代码,在适当的时候执行,一般用于一些耗时操作,也可以传递值
    • 区别:block类似于匿名函数,而闭包就是用来定义函数的,Swift中的函数其实就是闭包
    • 注意:Swift中,要求一个类的属性必须有初始值,如果没有,可以写个问号表示是可选类型。也就是说,如果类的属性不是可选类型,那么必须有初始化值
    • 所以,在viewController中定义一个闭包,也必须有个初始值,或者加个问号。
      • 注意问号的位置,如果直接放在了后面一个括号后面,表示返回值是可选类型,而我们现在要表示闭包是可选类型。所以要把闭包整体括起来,把问号放在后面
    // 定义一个闭包属性(类似OC的strong属性)
    // 返回值为空,那么可以用()代替
    var finished: (() -> ())?
    
    • 定义完属性,在viewDidLoad中给他初始化
    • 格式:
    //类型的格式:(形参列表) -> 返回值类型
    //值的格式:
    {
        (形参列表) -> 返回值类型
        in // in的作用是分隔需要执行的代码
        需要执行的代码
    }
    
    • 示例:没有形参,没有返回值的闭包
    self.finished = {
        () -> ()
        in
        print("我被调用了")
    }
    // 调用,此处加叹号是因为必须保证闭包中有值才能调用(类似OC中block也必须先判断block是否有值)
    self.finished!()
    
    • 注意点
      • Swift中self用的比较少,一般仅用于闭包中,所以看到self就要想起闭包

    具体使用

    • 经典子线程耗时操作,主线程更新UI
    dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
    
        print("执行了耗时操作")
    
        print(NSThread.currentThread())
    
        
    
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
    
            print("更新了UI")
    
            print(NSThread.currentThread())
    
        })
    
    }
    
    • 用闭包封装一个创建scrollView的方法,并且在scrollView里创建子控件。创建的子控件类型和个数由调用者决定
      • 这个示例中,闭包的返回值由调用者传给方法,而闭包中的参数是由方法传给调用者
    func creatScrollView(btnCount: ()-> Int, btnWithIndex: (index:Int) ->UIView) -> UIScrollView
    
        {
    
            let sc = UIScrollView(frame: CGRect(x: 0, y: 100, width: 375, height: 44))
    
            sc.backgroundColor = UIColor.redColor()
    
            let count = btnCount()
    
            for i in 0..<count
    
            { // subView由调用者决定,而index由这里决定并传给调用者
    
                let subView = btnWithIndex(index: i)
    
                sc.addSubview(subView)
    
                sc.contentSize = CGSize(width: CGFloat(count) * subView.bounds.width, height: 44)
    
            }
    
            
    
            return sc
    
        }
    // 调用
    let sc = creatScrollView({ () -> Int in
    
                return 15
    
                }) { (index) -> UIView in
    
                    let width = 80
    
                    let btn = UIButton()
    
                    btn.backgroundColor = UIColor.greenColor()
    
                    btn.setTitle("标题\(index)", forState: UIControlState.Normal)
    
                    btn.frame = CGRect(x: index * width, y: 0, width: width, height: 44)
    
                    return btn
    
            }
    
            view.addSubview(sc)
    

    闭包的简写

    • 来个带闭包的函数,并且调用
    func loadData(finished: ()->())
    
    {
    
        print("执行了耗时操作")
    
        // 调用闭包
    
        finished()
    
    }
    
    loadData ({ () -> () in
    
        print("耗时操作执行完毕")
    
    })
    
    • 如果闭包没有参数,那么in和in之前的闭包格式符号可以省略
    • 如果闭包是函数形参列表的最后一个形参,那么可以把闭包写到圆括号后面
    • 如果形参列表只有闭包一个参数,那么圆括号可以省略(系统就是这么做的)
    • 于是调用上面那个函数就变成了这样
    loadData {
        print("耗时操作执行完毕")
    }
    

    闭包的循环引用

    • 在闭包中使用外接对象,为了在调用闭包的时候保证这个对象没有被释放,必须对这个外界对象加一个self.意思是对其进行强引用
    • 如果把一个闭包保存为控制器的属性,在这个闭包中又调用了控制器的view,用到了self(控制器),那么就会导致强引用循环
    • 类似于OC,设置一个weakSelf即可解决这个问题
      • 注意在闭包中使用weakSelf的时候要加问号。因为是weak的表示弱引用,随时可能释放,可能是nil;而只要有可能是nil的对象必须是可选类型。可以直接强制解包告诉它一定有值,问号改成感叹号
    weak var weakSelf = self
    loadData ({ () -> () in
    
        print("耗时操作执行完毕")
        weakSelf!.view.backgroundColor = UIColor.redColor
    
    })
    
    • 还有个写法:可以在闭包的形参列表圆括号前加上[weak self],表示在此闭包中调用的self都是weak的
    loadData ({ [weak self] () -> () in
    
        print("耗时操作执行完毕")
        self!.view.backgroundColor = UIColor.redColor
    
    })
    
    • 解决方式二:用__unsafe_unretained
      • OC中weak的特点:如果对象被释放,会自动赋值为nil
      • OC中__unsafe_unretained的特点:如果对象被释放,不会赋值为nil,而是指向了一块坏内存。可以用这个来解决block的循环引用问题
      • Swift可以用unowned来达到相同的效果。注意不用加问号或者叹号了,因为释放后不会是nil
    loadData ({ [unowned self] () -> () in
    
        print("耗时操作执行完毕")
        self.view.backgroundColor = UIColor.redColor
    
    })
    

    相关文章

      网友评论

        本文标题:swift-基础-闭包

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