美文网首页
swift3.0 - 闭包

swift3.0 - 闭包

作者: 07212a79db66 | 来源:发表于2016-08-11 16:16 被阅读370次

    闭包的介绍

    函数是闭包的一种
    类似于OC语言的block
    闭包表达式(匿名函数) -- 能够捕获上下文中的值

    语法: in关键字的目的是便于区分返回值和执行语句
    闭包表达式的类型和函数的类型一样, 是参数加上返回值, 也就是in之前的部分
    {
    (参数) -> 返回值类型 in
    执行语句
    }

    闭包简写

    • 1.如果没有参数, 没有返回值, in和in之前的东西可以省略
    • 2.如果闭包是函数的最后一个参数, 可以写在()后面 -- 尾随闭包
    • 3.如果只有一个闭包参数, 那么()也可以省略 -- 尾随闭包

    闭包使用:使用闭包代替block

    • 定义网络请求的类
    class HttpRequestTool: NSObject {
    
        var callBack:(()->())?
        
        func loadData(callBack: () -> ()) {
            
            self.callBack = callBack
            DispatchQueue.global(attributes: DispatchQueue.GlobalAttributes(rawValue: UInt64(0))).async {
                print("网络请求数据:", Thread.current())
                DispatchQueue.main.async(execute: {
                    callBack()
                })
            }
        }  
    }
    
    
    • 进行网络请求,请求到数据后利用闭包进行回调
    class ViewController: UIViewController {
    
        var httpTools : HttpRequestTool = HttpRequestTool()
        
        
        override func viewDidLoad() {
            super.viewDidLoad()
         
            httpTools.loadData { 
                print("加载数据完成,更新界面:", Thread.current())
            }
            
        } 
    }
    

    闭包的循环引用

    • 如果在HttpTool中有对闭包进行强引用,则会形成循环引用
    • 在Swift中检测一个对象是否销毁,可以实现对象的deinit函数

    在xcode8可以利用内存图分析循环引用:
    例如:这样写会造成循环引用

    
    httpTools.loadData { 
                print("load data finish")
                self.view.backgroundColor = UIColor.red()
            }
            
            deinit {
            print("控制器销毁了")
        }
            
    

    通过内存分析图查看表现为:

    绿色的为出现循环引用.并且没用打印控制器销毁.改为如下代码:

    weak var weakSelf = self
            httpTools.loadData { 
                print("load data finish")
                weakSelf?.view.backgroundColor = UIColor.red()
            }
            
            deinit {
            print("控制器销毁了")
        }
    

    通过内存分析图查看表现为:

    绿色消除,打印控制器销毁

    // 析构函数(相当于OC中dealloc方法)
        deinit {
            print("ViewController----deinit")
        }
        
    

    swift中解决循环引用的方式

    • 方案一:使用weak,对当前控制器使用弱引用,但是因为self可能有值也可能没有值,因此weakSelf是一个可选类型,在真正使用时可以对其强制解包(该处强制解包没有问题,因为控制器一定存在,否则无法调用所在函数)
    
     weak var weakSelf = self
            httpTools.loadData { 
                print("load data finish")
                weakSelf?.view.backgroundColor = UIColor.red()
            }
            
    
    • 方案二:和方案一类型,只是书写方式更加简单,可以写在闭包中,并且在闭包中用到的self都是弱引用
    
    httpTools.loadData {[weak self] () -> () in
                print("load data finish")
                self?.view.backgroundColor = UIColor.red()
         }
         
    
    • 方案三:使用关键字unowned,从行为上来说 unowned 更像OC中的 unsafe_unretained,unowned 表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个 "无效的" 引用,它不能是 Optional 值,也不会被指向 nil
     httpTools.loadData {[unowned self] () -> () in
                print("load data finish")
                self.view.backgroundColor = UIColor.red()
            }
    

    相关文章

      网友评论

          本文标题:swift3.0 - 闭包

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