美文网首页
08Swift基本语法(闭包)

08Swift基本语法(闭包)

作者: i爱吃土豆的猫 | 来源:发表于2016-08-03 14:01 被阅读8次

0. 闭包

  • 与 OC 中的 Block 类似,
  • 闭包主要用于异步操作执行完成后的代码回调,网络访问结果以参数的形式传递给调用方

1 闭包的定义

1.1 定义一个函数
//: 定义一个 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)
1.2定义一个闭包
  • 闭包 = { (行参) -> 返回值 in // 代码实现 }
  • in 用于区分函数定义和代码实现
//: 闭包 = { (行参) -> 返回值 in // 代码实现 }
let sumFunc = { (num1 x: Int, num2 y: Int) -> Int in 
    return x + y
}
sumFunc(num1: 10, num2: 20)
1.3 最简单的闭包,如果没有参数/返回值,则 参数/返回值/in
let demoFunc = { 
    print("hello")
}

2. 闭包基本使用

2.1 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())") 
    }
}
2.2 自定义闭包参数,实现主线程回调

1.添加没有参数,没有返回值的闭包

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() 
                   } 
            }
 }

2.添加回调参数

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>") 
        } 
    }
}

3. 闭包的循环引用

  • 建立 NetworkTools对象

    class NetworkTools: NSObject { 
    
    /// 加载数据  
    /// - parameter finished: 完成回调 
    func loadData(finished: () -> ()) { 
          print("开始加载数据...") 
    
          // ... 
          finished() 
     } 
    
    deinit { 
          print("网络工具 88") 
     }
    }
    
  • 实例化 NetworkTools并且加载数据

    //运行不会形成循环引用,因为 loadData 执行完毕后,就会释放对 self 的引用
    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") 
          }
    }
    
  • 修改 NetworkTools,定义回调闭包属性

    // 运行测试,会出现循环引用
    /// 完成回调属性
    var finishedCallBack: (()->())?
    
    /// 加载数据
    /// - parameter finished: 完成回调
    func loadData(finished: () -> ()) { 
    
          self.finishedCallBack = finished 
    
          print("开始加载数据...") 
    
          // ... 
          working()
    }
    
    func working() { 
          finishedCallBack?()
    }
    
    deinit { 
          print("网络工具 88")
    }
    

4. 解除循环引用

1.OC 类似的方法
/// 类似于 OC 的解除引用
func demo() { 
    weak var weakSelf = self 
    tools?.loadData() { 
        print("\(weakSelf?.view)") 
    }
}
2. Swift 推荐的方法
loadData { [weak self] in 
    print("\(self?.view)")
}

或者

loadData { [unowned self] in 
    print("\(self.view)")
}

5. 闭包(Block) 的循环引用小结

  1. Objc
    1.__weak typeof(self) weakSelf;
    如果self已经被释放,则为nil

    2.__unsafe_unretained typeof(self) weakSelf;
    如果self已经被释放,则出现野指针访问
    
  2. Swift
    1.[weak self]
    self是可选项,如果self已经被释放,则为nil

    2.[unowned self]
    self不是可选项,如果self已经被释放,则出现野指针访问
    

文/greedyDoor(简书作者)原文链接:http://www.jianshu.com/p/bbb9d6c636f4著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

相关文章

  • 08Swift基本语法(闭包)

    0. 闭包 与 OC 中的 Block 类似, 闭包主要用于异步操作执行完成后的代码回调,网络访问结果以参数的形式...

  • Swift 2 学习笔记 9.闭包

    课程来自慕课网liuyubobobo老师 闭包 闭包的基本语法 闭包语法的简化 结尾闭包 内容捕获 闭包和函数是引用类型

  • 闭包

    闭包的基本语法 闭包的内容捕获 闭包和函数的引用类型

  • 闭包-Closures [swift 5.1]

    闭包的语法 尾随闭包 闭包逃离 自动闭包

  • swift语法--12-1闭包基本概念

    swift语法--12-1闭包基本概念 block和闭包区别 OC:block类似于匿名函数, 用于封装代码块, ...

  • Swift~ @escaping @noescaping 逃逸

    闭包表达式语法 闭包表达式语法有如下的一般形式: 闭包只有在函数中做参数时,才会区分逃逸闭包和非逃逸闭包 Swif...

  • 闭包和jQuery基本语法

    闭包 1、闭包的用途:存循环的索引值函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾回收机...

  • Swift 基本语法(函数, 闭包)

    前言 接上篇, 这篇聊一下 Swift中的 函数, 闭包 一 函数 二 闭包 Swift 基础 先介绍三篇, ...

  • Swift基本语法之闭包

    Swift基本语法之初体验-常量变量-数据类型 Swift基本语法之逻辑分支 Swift基本语法之循环 Swift...

  • JavaScript----闭包

    javascript之闭包 闭包的概念     闭包(closure)是 JavaScript 的一种语法特性。 ...

网友评论

      本文标题:08Swift基本语法(闭包)

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