08Swift基本语法(闭包)
2016-08-03 本文已影响8人
i爱吃土豆的猫
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) 的循环引用小结
-
Objc
1.__weak typeof(self) weakSelf;
如果self已经被释放,则为nil2.__unsafe_unretained typeof(self) weakSelf; 如果self已经被释放,则出现野指针访问
-
Swift
1.[weak self]
self是可选项,如果self已经被释放,则为nil2.[unowned self] self不是可选项,如果self已经被释放,则出现野指针访问
文/greedyDoor(简书作者)原文链接:http://www.jianshu.com/p/bbb9d6c636f4著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。