Swift中的闭包
Swift中的闭包和OC中的block大致相同,OC中的block相当于匿名函数,而Swift中的闭包也相当于特殊的函数。 闭包的数据类型格式为: (参数列表) -> (返回值类型)
下面用一个异步网络请求的案例来简单使用一下闭包:
首先创建模拟网络请求类⬇️
import UIKit
class HWHttpTools: NSObject {
func requestWith(url : String, _ finishedCallBlock : @escaping (_ succeed : Bool, _ data : Data?)->()) {
DispatchQueue.global().async {
print("发起异步请求 - \(Thread.current)")
DispatchQueue.main.async {
print("请求成功回到主线程 - \(Thread.current)")
finishedCallBlock(true, nil)
}
}
}
}
在控制器中点击view利用网络工具类发起网络请求
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
HWHttpTools().requestWith(url: "服务器url字符串") { (succeed : Bool, data : Data?) in
if succeed {
print("网络请求成功 - \(Thread.current)")
}
}
}
}
点击view打印结果⬇️
发起异步请求 - <NSThread: 0x6080002613c0>{number = 3, name = (null)}
请求成功回到主线程 - <NSThread: 0x60000007a9c0>{number = 1, name = main}
网络请求成功 - <NSThread: 0x60000007a9c0>{number = 1, name = main}
闭包衍生的循环引用问题
在上面的案例中,我们故意在控制器闭包回调中添加一句更改view视图背景颜色的代码,看看是否会发生循环引用问题。(我们把网络工具类对象设置成控制器的一个强引用属性)
import UIKit
class ViewController: UIViewController {
var httpTools : HWHttpTools?
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
httpTools = HWHttpTools()
httpTools?.requestWith(url: "服务器url字符串") { (succeed : Bool, data : Data?) in
self.view.backgroundColor = UIColor.red
}
}
}
但是万一在闭包中发生了循环引用问题,在Swift当中我们应该怎么处理呢?首先我们先让工具类对象强引用闭包。⬇️
import UIKit
class HWHttpTools: NSObject {
var finishedCallBlock : ((_ succeed : Bool, _ data : Data?)->())?
func requestWith(url : String, _ finishedCallBlock : @escaping (_ succeed : Bool, _ data : Data?)->()) {
self.finishedCallBlock = finishedCallBlock
DispatchQueue.global().async {
print("发起异步请求 - \(Thread.current)")
DispatchQueue.main.async {
print("请求成功回到主线程 - \(Thread.current)")
finishedCallBlock(true, nil)
}
}
}
}
然后再控制器中出现循环引用,我们采取使用在闭包外部将控制器self赋值给weak修饰的变量来阻断闭包对控制器的强引用。⬇️
import UIKit
class ViewController: UIViewController {
var httpTools : HWHttpTools?
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
httpTools = HWHttpTools()
weak var weakSelf = self
httpTools?.requestWith(url: "服务器url字符串") { (succeed : Bool, data : Data?) in
weakSelf?.view.backgroundColor = UIColor.red
}
}
}
闭包循环引用问题另一种解决写法(简便写法)
import UIKit
class ViewController: UIViewController {
var httpTools : HWHttpTools?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
httpTools = HWHttpTools()
httpTools?.requestWith(url: "服务器url字符串") { [weak self] (succeed : Bool, data : Data?) in
self?.view.backgroundColor = UIColor.red
}
}
deinit {
print("控制器销毁")
}
}
PS : 还有一种写法是将上面的 [weak self] 改写成 [unowned self] 效果是一样的,但是使用 unowned 是很危险的容易出现操作野指针,unowned 的意思跟OC当中的__unsafe_unretained一样 只不过保证 self 不被销毁就可以安全使用。
尾随闭包
当函数参数中的闭包参数是最后一个,在函数调用时闭包参数整个大括号可以写在参数列表小括号外面(紧跟在后面)
HWHttpTools().function(name: "参数一", {
})
HWHttpTools().function(name: "参数一") {
}
当函数只有一个参数,且是闭包参数,那么可以在函数调用的时候省去()小括号,如下3种写法均可:
HWHttpTools().function({
})
HWHttpTools().function() {
}
HWHttpTools().function {
}
Swift中的懒加载
懒加载特性 : 1.用到时才会加载;2.程序运行过程中只会创建一次
在OC中的懒加载我们通常是通过重写其getter方法来实现的,但是在Swift中专门提供了一个关键字 lazy 来修饰懒加载属性,具体写法如下:
lazy var names : [String] = Array()
lazy var items : [String] = {
let items : [String] = Array()
return items
}()
在开发中,很多控件也使用懒加载,用到即加载到内存中。
lazy var btn : UIButton = UIButton()
lazy var btn : UIButton = {
let btn = UIButton()
btn.setTitle("按钮", for: .normal)
btn.setBackgroundImage(UIImage(named: "xx.png"), for: .normal)
return btn
}()
Swift中的访问权限
在Swift3.0中规定访问权限的关键词有 internal 、 open、 private、 fileprivate。
这些访问权限关键词不仅可以修饰属性,也可以修饰方法和类。
internal : 默认修饰词(属性、类、方法默认权限修饰词),表示在同一个模块(target、项目、资源包)中都能够访问。
open : 表示跨项目(target、项目、资源包)都能够使用。
private : 表示只能在当前类中访问。
fileprivate : 表示只能在当前文件中使用。
Swift中零散知识点
1.在Swift开发中,并不是所有的方法都写在一个类中,这样可读性也不会很好。如果能够灵活运用延展,就可以有效提高代码的可读和美观性。但是注意 : 在延展中的方法不能用private修饰,不然在当前类中也无法访问,只能在延展中使用,但是可以用fileprivate修饰。
2.在Swift开发中,监听方法若用 private 或 fileprivate 修饰必须前面加上 @objc 修饰词。(什么是监听方法 : 比如写在
3.在Swift中分栏注释(提高代码阅读性)
Swift3.0小案例
小案例目的在于综合运用Swift3.0写一个页面,中间设计网络请求、控件搭建、图片加载、转换数据模型等。
源代码地址 : https://github.com/IMLoser/Swift3.0_Demo