Error 異常處理 錯(cuò)誤處理
錯(cuò)誤類型
1.語法錯(cuò)誤(編譯報(bào)錯(cuò))
2.邏輯錯(cuò)誤
3.運(yùn)行時(shí)錯(cuò)誤 (可能會(huì)導(dǎo)致閃退 一般也叫做異常)
自定義錯(cuò)誤
可以通過Error協(xié)議自定義運(yùn)行時(shí)的錯(cuò)誤信息
enum SomeError: Error {
case illegalArg(String)
case outOfBounds(Int, Int)
case outOfMemory
}
函數(shù)內(nèi)部通過throw拋出自定義Error 可能會(huì)拋出Error的函數(shù)必須加上throws聲明
struct MyError: Error {
var msg: String
}
func divide(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw MyError(msg: "0不能作為除數(shù)")
}
return num1 / num2
}
需要使用try調(diào)用可能會(huì)拋出Error的函數(shù)
var result = try divide(2, 0)
print(result)

錯(cuò)誤提示.png
如何處理錯(cuò)誤
do-catch
一旦 try 拋出異常 它所在作用域范圍內(nèi)的后面的所有代碼都不會(huì)執(zhí)行
func test() {
print("1")
do {
print("2")
print(try divide(20, 0))
print("3")
}catch let SomeError.illegalArg(msg){
print("參數(shù)異常:", msg)
}catch let SomeError.outOfBounds(size, index){
print("下標(biāo)越界:", "size = \(size)", "index = \(index)")
}catch SomeError.outOfMemory{
print("內(nèi)存溢出")
}catch {
print("其他錯(cuò)誤")
}
print("4")
}
test()
1
2
參數(shù)異常: 0不能作為除數(shù)
4
不捕捉Error 在當(dāng)前函數(shù)增加throws聲明 Error將自動(dòng)拋給上層函數(shù)
- 如果最頂層函數(shù)(main 函數(shù)) 依然沒有捕捉Error 那么程序?qū)⒔K止
func test() throws{
print(try divide(20, 0))
}
try test()
func test() throws{
print("1")
do {
print("2")
print(try divide(20, 0))
print("3")
}catch let error as SomeError{
print(error)
}
print("4")
}
try test()
1
2
illegalArg("0不能作為除數(shù)")
4
異常一層一層拋出
func test0 throws {
try test1()
}
func test1 throws {
try test2()
}
func test2 throws {
do{
print(try divide(288, 81))
}catch is SomeError {
priht("This is SomeError")
}
}
try test0()
try? try!
可以使用try? try! 調(diào)用可能會(huì)拋出Error的函數(shù) 這樣就不用去處理Error
func test() {
print("1")
var result1 = try? divide(20, 10)
var result2 = try? divide(20, 0)
var result3 = try! divide(20, 10)
print("2")
}
test()
a b 是等價(jià)
var a = try? divide(20, 0)
var b: Int?
do {
b = try divide(20, 0)
}catch{
b = nil
}
rethrows
rethrows 函數(shù)本身不會(huì)拋出錯(cuò)誤 但是調(diào)用閉包函數(shù)拋出錯(cuò)誤 那么他會(huì)將錯(cuò)誤往上拋
rethrows 跟 throws 一樣拋出異常 只不過 rethrows是由于函數(shù)參數(shù)是閉包函數(shù)導(dǎo)致的異常
func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows {
print(try fn(num1,num2))
}
try exec(divide, 29, 0)
defer
用來定義以任何方式(拋錯(cuò)誤 return等) 離開代碼前必須要執(zhí)行的代碼
defer語句將延遲至當(dāng)前作用域結(jié)束之前執(zhí)行
func open(_ filename: String) -> Int {
print("open")
return 0
}
func close(_ file: Int) {
print("close")
}
func processFile(_ filename: String) throws {
let file = open(filename)
defer {
close(file)
}
try divide(20, 0)
}
try processFile("test.text")
defer語句的執(zhí)行順序與定義順序相反
泛型 Generics
泛型可以將類型參數(shù)化 提供代碼復(fù)用率 減少代碼量
T 代表一種不確定的類型
var n1 = 10
var n2 = 20
func swapValues<T>(_ a: inout T , _ b: inout T) {
return (a,b) = (b,a)
}
swap(&n1, &n2)
print(n1,n2)
函數(shù)類型 必須明確是什么類型
var fn: (inout Int, inout Int) -> () = swapValues
泛型類型
class Stack<E> {
var elements = [E]()
func push(_ element: E){
return elements.append(element)
}
func pop() -> E {
return elements.removeLast()
}
func top() -> E {
return elements.last!
}
func size() -> Int {
return elements.count
}
}
var stack = Stack<Int>()
stack.push(<#T##element: Int##Int#>)
class SubStack<E>: Stack<E> {
}
enum Score<T> {
case point(T)
case grade(String)
}
let score = Score<Int>.grade("A")
關(guān)聯(lián)類型
1.關(guān)聯(lián)類型的作用 給協(xié)議中用到的類型定義一個(gè)占位名稱
2.協(xié)議中擁有多個(gè)關(guān)聯(lián)類型
protocol Stackable {
associatedtype Element //關(guān)聯(lián)類型
mutating func push(_ element: Element)
mutating func pop() -> Element
func top() -> Element
func size() -> Int
}
class StringSatck: Stackable {
//給關(guān)聯(lián)類型設(shè)定真實(shí)類型
typealias Element = String
func push(_ element: Element){
return elements.append(element)
}
func pop() -> Element{
return elements.removeLast()
}
func top() -> Element {
return elements.last!
}
func size() -> Int {
return elements.count
}
}
類型約束

A2CAAC5E-23BD-4087-823D-3E71156FBCEE.png
協(xié)議類型的注意點(diǎn)

F305714F-FF8A-41D9-A4E8-7F8CF6B9201D.png
如果協(xié)議中有associatedtype 會(huì)報(bào)錯(cuò)

D8138A36-3309-4454-AB3B-7C7FAF4031F9.png

83EF3C18-E8C5-4D50-9F1F-1575303C1BBB.png

BB53C5DD-A45E-4230-8006-454839C403A9.png
不透明類型 是為了只開放類型里面的部分接口 (也就是協(xié)議里面定義的接口) 不暴露類型