Swift中的闭包

原创
2015/12/08 21:01
阅读数 9

闭包的定义

  • 定义一个函数

//: 定义一个 sum 函数func sum(num1 num1: Int, num2: Int) -> Int {    return num1 + num2
}
sum(num1: 10, num2: 30)//: 在 Swift 中函数本身就可以当作参数被定义和传递let mySum = sumlet 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

    • self不是可选项,如果self已经被释放,则出现野指针访问

    • self是可选项,如果self已经被释放,则为nil

    • [weak self]

    • [unowned self]

  • Objc

    • 如果self已经被释放,则出现野指针访问

    • 如果self已经被释放,则为nil

    • __weak typeof(self) weakSelf;

    • __unsafe_unretained typeof(self) weakSelf;

这些东西是自己的一些见解,如果有大牛有不同见解,请多多交流


展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部