swift3.0 - 闭包

闭包的介绍

函数是闭包的一种
类似于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("控制器销毁了")
    }
        

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

swift3.0 - 闭包_第1张图片

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

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

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

swift3.0 - 闭包_第2张图片

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

// 析构函数(相当于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 - 闭包)