09-closure
来源:互联网 发布:域名指向两个ip 编辑:程序博客网 时间:2024/06/06 03:46
闭包
- 闭包类似于 OC 中的 Block
- 预先定义好的代码
- 在需要时执行
- 可以当作参数传递
- 可以有返回值
- 包含
self
时需要注意循环引用
定义
- 定义一个函数
//: 定义一个 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: Int, num2: Int) -> Int = { (x, y) -> Int in return x + y}sumFunc(num1: 10, num2: 50)
闭包实战
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("完成了 \(NSThread .currentThread())") }}func loadData(finished: () -> ()) { dispatch_async(dispatch_get_global_queue(0, 0)) { print("耗时操作 \(NSThread .currentThread())") dispatch_async(dispatch_get_main_queue()) { // 执行回调 finished() } }}
- 添加回调参数
override func viewDidLoad() { super.viewDidLoad() loadData { message in print(message + " \(NSThread .currentThread())") }}func loadData(finished: (msg: String) -> ()) { dispatch_async(dispatch_get_global_queue(0, 0)) { print("耗时操作 \(NSThread .currentThread())") dispatch_async(dispatch_get_main_queue()) { // 执行回调 finished(msg: "over") } }}
闭包的返回值演练
目标:用闭包实现
网易新闻
中滚动标签视图
- 实现
scrollView
函数,返回UIScrollView
func scrollView(frame: CGRect, numbersOfLabel: ()-> Int, labelForIndex: (index: Int) -> UILabel) -> UIScrollView { // 1. 实例化 scrollView let sv = UIScrollView(frame: frame) // 2. label 的数量 let count = numbersOfLabel() print(count) // 3. 循环创建 label 的内容 let margin: CGFloat = 8 var x = margin for i in 0..<count { let label = labelForIndex(index: i) label.frame = CGRect(x: x, y: 0, width: label.bounds.width, height: frame.height) sv.addSubview(label) // 累加 x 坐标 x += label.bounds.width } // 4. 设置 scrollView 的 contentSize sv.contentSize = CGSize(width: x, height: frame.height) // 5. 返回 return sv}
- 函数调用
override func viewDidLoad() { super.viewDidLoad() let size = UIScreen.mainScreen().bounds.size let rect = CGRect(x: 0, y: 20, width: size.width, height: 44) view.addSubview(scrollView(rect, numbersOfLabel: { () -> Int in return 10 }) { (index) -> UILabel in // 1. 实例化 label let label = UILabel() // 2. 设置文本内容 label.text = "Hello \(index)" // 2.1 设置字体 & 对齐方式 label.font = UIFont.systemFontOfSize(18) label.textAlignment = NSTextAlignment.Center // 2.2 自动设置大小 label.sizeToFit() // 2.3 缩小字体 label.font = UIFont.systemFontOfSize(14) return label })}
本演练不仅演示了闭包返回值的应用,同时也模拟了
TableView
的数据源方法用闭包的实现思路
- 自定义视图
class ChannelView: UIScrollView { init(frame: CGRect, numbersOfLabel: ()-> Int, labelForIndex: (index: Int) -> UILabel) { // 1. 实例化 scrollView super.init(frame: frame) // 2. label 的数量 let count = numbersOfLabel() print(count) // 3. 循环创建 label 的内容 let margin: CGFloat = 8 var x = margin for i in 0..<count { let label = labelForIndex(index: i) label.frame = CGRect(x: x, y: 0, width: label.bounds.width, height: frame.height) addSubview(label) // 累加 x 坐标 x += label.bounds.width } // 4. 设置 scrollView 的 contentSize contentSize = CGSize(width: x, height: frame.height) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }}
闭包的循环引用
- 代码准备
// 完成回调属性,控制器对闭包强引用var finishedBlock: (() -> ())?private func loadData(finished: () -> ()) { // 记录闭包 finishedBlock = finished working()}private func working() { // 如果属性不存在,使用 ! 会崩溃 // finishedBlock!() // 如果属性不存在,就不执行 finishedBlock?()}
- 调用闭包,与 Block 一致,闭包会对
self
做一次 copy,从而进行强引用
loadData { print("\(self.view)")}
- 测试视图控制器的释放
/// 与 OC 中的 dealloc 类似,注意此函数没有()deinit { print("\(classForCoder) 88")}
解除循环引用
- 与 OC 类似的方法
weak var weakSelf = selfloadData { 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
已经被释放,则出现野指针访问
- 如果
0 0
- 09-closure
- Closure
- closure
- closure
- Closure
- closure
- Closure
- Closure
- closure
- Closure
- JavaScript - Closure
- Closure入门
- google closure
- Closure介绍
- js closure
- google closure
- Javascript Closure
- javascript Closure
- loop
- String
- 07-collection
- 08-func
- 【HDU2112】一道很猥琐的最短路水题。。
- 09-closure
- 【小熊刷题】Merge K Sorted Linked Lists
- hdu 5381 The sum of gcd (线段树x树状数组x区间和维护进阶x离线处理)
- 10-init_func
- 11-lazy
- 12-ats
- pyspider连接rabbitmq ,结果出现socket.error: [Errno 104] Connection reset by peer 这样的报错信息
- 宇枫工作室介绍
- matlab编程服务