【学习】重学Swift5-错误处理、三方库等
九、其他话题
-
错误处理
enum VendingMachineError: Error { case invalidSelection case insufficientFunds(coinsNeed: Int) case outOfStock } struct Item { var price: Int var count: Int } class VendingMachine { var inventory = [ "Candy Bar": Item.init(price:12, count: 7), "Chips": Item.init(price: 20, count: 0), "Bread": Item.init(price:15, count:5) ] var coinsDecposited = 0 func vend(itemName: String) throws { defer { print("推出清理") } print("开始售卖") guard let item = inventory[itemName] else { throw VendingMachineError.invalidSelection } guard item.count > 0 else { throw VendingMachineError.outOfStock } guard coinsDecposited >= item.price else { throw VendingMachineError.insufficientFunds(coinsNeed: item.price) } coinsDecposited -= item.price var newItem = item newItem.count -= 1 inventory[itemName] = newItem print("售卖成功") } } var machine = VendingMachine() machine.coinsDecposited = 5 do { try machine.vend(itemName: "Chips") } catch VendingMachineError.invalidSelection { print("没有当前商品") } catch VendingMachineError.insufficientFunds(let coinsNeeded) { print("你需要投\(coinsNeeded)币") } catch VendingMachineError.outOfStock { print("已售空") } catch { print("未知错误") } // throw 抛出异常 do-catch处理异常 defer
-
权限控制
// open public internal fileprivate private /* 1.类成员的访问级别不能高于类的访问级别; 2.常量、变量、属性、下标脚本访问级别低于其所声明的类型级别,并且如果不是默认访问级别(internal)要明确声明访问级别。 3.在不违反1、2的情况下,setter的访问级别可以抵御getter的访问级别。 4.必要构造方法(required修饰)的访问级别必须和类访问级别相同,狗狗剃的默认逐一构造函数的访问级别不高于其成员的访问级别,其他方法的访问级别遵循规则1 */
-
不透明类型
-
自动引用计数
// 循环引用 // 弱引用weak(对生命周期中引用会变为nil的实例,只能声明变量类型) 无主引用unowned(对初始化赋值之后引用再也不会赋值为nil的实例,无主引用默认始终有值,只能定义为非可选类型) // 闭包的循环引用 lazy var someColisure = { [unowned self, weak delegate = self.delegate](index: Int, stringToProgress: String) -> String in // code }
-
内存安全
十、常见三方库
Alamofire SwiftJSON R.Swift MonkeyKing Kingfisher SnnapKit Dollar
十一、加餐
1.可选链、
2.KVC
· 继承自NSObject的类,标记@objc的属性可以使用setValue:(_ forKey:)
· 非继承自NSObject的类和结构体,使用索引+参数值
struct ValueType {
var name: String
}
var object = ValueType.init(name: "Objective-c")
// set
object[keyPath: \ValueType.name] = "swift"
// get
let valueOfName = object[keyPath: \ValueType.name]
print(valueOfName)
3.KVO
// 只有NSObject才能支持KVO,且要观察的属性必须使用@objc dynamic修饰
// 方法一
class Person: NSObject {
@objc dynamic var age = 0
}
class ViewController: UIViewController {
let p = Person()
override func viewDidLoad() {
super.viewDidLoad()
p.addObserver(self, forKeyPath: "age", options: [.new, .old], context: nil)
p.age = 33
// Do any additional setup after loading the view.
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "age" {
print(change as Any)
}
}
}
// 方法二
class Person: NSObject {
@objc dynamic var age = 0
}
class ViewController: UIViewController {
@objc dynamic let p = Person()
var ob: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
self.ob = observe(\.p.age, options: [.new, .old], changeHandler: { (_ , change) in
print(change as Any)
})
p.age = 33
// Do any additional setup after loading the view.
}
}