关于swift中的"闭包"
闭包的定义
- 定义一个函数
//: 定义一个 sum 函数
func sum(num1 num1: Int, num2: Int) -> Int {
    return num1 + num2
}
sum(num1: 10, num2: 30)
//: 在 Swift 中函数本身就可以当作参数被定义和传递
let mySum = sum
let result = mySum(num1: 20, num2: 30)
- 定义一个闭包
- 闭包 = { (行参) -> 返回值 in // 代码实现 }
- in用于区分函数定义和代码实现
 
//: 闭包 = { (行参) -> 返回值 in // 代码实现 }
let sumFunc = { (num1 x: Int, num2 y: Int) -> Int in
    return x + y
}
sumFunc(num1: 10, num2: 20)
- 最简单的闭包,如果没有参数/返回值,则 参数/返回值/in统统都可以省略- { 代码实现 }
 
let demoFunc = {
    print("hello")
}
基本使用
GCD 异步
- 模拟在后台线程加载数据
func loadData() {
    dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
        print("耗时操作 \(NSThread .currentThread())")
    })
}
- 尾随闭包,如果闭包是最后一个参数,可以用以下写法
- 注意上下两段代码,}的位置
func loadData() {
    dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
        print("耗时操作 \(NSThread .currentThread())")
    }
}
- 闭包的简写,如果闭包中没有参数和返回值,可以省略
func loadData() {
    dispatch_async(dispatch_get_global_queue(0, 0)) {
        print("耗时操作 \(NSThread .currentThread())")
    }
}
自定义闭包参数,实现主线程回调
- 添加没有参数,没有返回值的闭包
override func viewDidLoad() {
    super.viewDidLoad()
    loadData {
        print("完成回调")
    }
}
// MARK: - 自定义闭包参数
func loadData(finished: ()->()) {
    dispatch_async(dispatch_get_global_queue(0, 0)) {
        print("耗时操作 \(NSThread.currentThread())")
        dispatch_sync(dispatch_get_main_queue()) {
            print("主线程回调 \(NSThread.currentThread())")
            // 执行回调
            finished()
        }
    }
}
- 添加回调参数
override func viewDidLoad() {
    super.viewDidLoad()
    loadData4 { (html) -> () in
        print(html)
    }
}
/// 加载数据
/// 完成回调 - 传入回调闭包,接收异步执行的结果
func loadData4(finished: (html: String) -> ()) {
    dispatch_async(dispatch_get_global_queue(0, 0)) {
        print("加载数据 \(NSThread.currentThread())")
        dispatch_sync(dispatch_get_main_queue()) {
            print("完成回调 \(NSThread.currentThread())")
            finished(html: "<h1>hello world</h1>")
        }
    }
}
循环引用
- 建立 NetworkTools对象
class NetworkTools: NSObject {
    /// 加载数据
    ///
    /// - parameter finished: 完成回调
    func loadData(finished: () -> ()) {
        print("开始加载数据...")
        // ...
        finished()
    }
    deinit {
        print("网络工具 88")
    }
}
- 实例化 NetworkTools并且加载数据
class ViewController: UIViewController {
    var tools: NetworkTools?
    override func viewDidLoad() {
        super.viewDidLoad()
        tools = NetworkTools()
        tools?.loadData() {
            print("come here \(self.view)")
        }
    }
    /// 与 OC 中的 dealloc 类似,注意此函数没有()
    deinit {
        print("控制器 88")
    }
}
运行不会形成循环引用,因为 loadData 执行完毕后,就会释放对 self 的引用
- 修改 NetworkTools,定义回调闭包属性
/// 完成回调属性
var finishedCallBack: (()->())?
/// 加载数据
///
/// - parameter finished: 完成回调
func loadData(finished: () -> ()) {
    self.finishedCallBack = finished
    print("开始加载数据...")
    // ...
    working()
}
func working() {
    finishedCallBack?()
}
deinit {
    print("网络工具 88")
}
运行测试,会出现循环引用
解除循环引用
- 与 OC 类似的方法
/// 类似于 OC 的解除引用
func demo() {
    weak var weakSelf = self
    tools?.loadData() {
        print("\(weakSelf?.view)")
    }
}
- Swift 推荐的方法
loadData { [weak self] in
    print("\(self?.view)")
}
- 还可以
loadData { [unowned self] in
    print("\(self.view)")
}
闭包(Block) 的循环引用小结
- 
Swift - [weak self]- self是可选项,如果self已经被释放,则为- nil
 
- [unowned self]- self不是可选项,如果self已经被释放,则出现- 野指针访问
 
 
- 
Objc - __weak typeof(self) weakSelf;- 如果self已经被释放,则为nil
 
- 如果
- __unsafe_unretained typeof(self) weakSelf;- 如果self已经被释放,则出现野指针访问
 
- 如果
 
    今天工作不努力,明天努力找工作.
 
                    
                     
                    
                 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号 
