Error/exception

  • Common development process errors
    • Syntax error (compilation error)
    • Logical error
    • Runtime error (may cause a flash back, also known as an exception)
    • .

Custom error

  • It can be passed in SwiftThe Error agreementCustom runtime error messages
    • Alamofire, for example, has a lot of errors defined
enum MyError: Error {
    case zero
    case outOfRange(Int, Int)
}
Copy the code
func divide(_ num1: Int, _ num2: Int) -> Int {
    returnnum1 / num2 } func divide1(_ num1: Int, _ num2: Int) -> Int? { guard num2 ! = 0else {
        return nil
    }
    returnnum1 / num2 } func divide2(_ num1: Int, _ num2: Int) throws -> Int { guard num2 ! = 0else {
        throw MyError.zero
    }
    return num1 / num2
}

print(divide(1, 2))
print(divide1(1, 0))
do {
    print("1")
    print(try divide2(1, 0))
    print("2")
} catch MyError.zero {
    print("zero")
} catch {
    print("other")}Copy the code

After an Error is thrown, the next line of the try will stop running until the end of the scope

Processing Error

  • Catch an Error with a do catch
  • If you do not capture an Error, add a throws declaration to the current function, and the Error is automatically thrown to the upper function

Error catch

  • catch is SomeError
  • catch let error as SomeError

try? And the try!

  • You can use try? And the try! Call a function that might raise an Error, so you don’t have to deal with errors
func test(_ i: Int) throws -> Int {
    if i == 0 {
        throw MyError.zero
    }
    return1}print("begin")
print(try? test(0))
print(try? test(1))
print(try! test(1))
print("end"/ / and the try?testPI of 0 is equivalent to var b: Int?do {
    b = try test= nil catch (0)} {b} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the execution result -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- begin nil Optional (1) 1 endCopy the code

rethrows

  • Rethrows indicates that the function itself does not throw an error, but calls to closure parameters throw an error, which it will throw upwards
func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows -> Int { } public func ?? <T>(optional: T? , defaultValue: @autoclosure () throws -> T) rethrows -> TCopy the code

defer

  • Used to define the code that must be executed before leaving the block in any way
  • Execution is deferred until the end of the current scope
func open() {
    print("open file")
}

func close() {
    print("close file")
}

func test(_ i: Int) throws -> Int {
    if i == 0 {
        throw MyError.zero
    }
    return 1
}

open()
defer {
    close()
}
try test(0)
Copy the code

The generic

func swapValue<T>(_ a: inout T, _ b: Inout T) {(a, b) = (b, a)} var a = 10 var b = 20 swap(&a, &b) var c = 10.0 var d = 20.0 & d) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- assembly analysis -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- movq$0xa, -0x8(%rbp)
movq   $0x14, -0x10(%rbp)
movq   0xd929(%rip), %rdx        ; (void *)0x00007fff8afc1b58: type metadata for Swift.Int
leaq   -0x8(%rbp), %rdi
leaq   -0x10(%rbp), %rsi
callq  0x10001182c               ; symbol stub for: Swift.swap<A>(inout A, inout A) -> ()
movq   0xd8f1(%rip), %rdx        ; (void *)0x00007fff8afc14e0: type metadata for
callq  0x10001182c               ; symbol stub for: Swift.swap<A>(inout A, inout A) -> ()
Copy the code

Self and double. self are passed in, and the method is found in the class information and executed

Associated Type

  • Associative types are used to define a placeholder name for the type used in the protocol
  • A protocol can have multiple association types
protocol Stackable {
    associatedtype Element: Equatable
}
Copy the code

Type constraints

That is, you can constrain generics

func swapValue<T: Equatable>(_ a: inout T, _ b: inout T) 
Copy the code

Opaque type

  • Use some to return only one type, not two
  • In addition to return value types, it can also be used for attribute types in general
  • Internal implementation reasons for masking: When protocol has an associated type, if it returns protocol then it has no way at compile time to determine which class it is
Class Person: Runnable {var speed: Int = 0} class Car: Runnable {var speed: Double = 0.0'Runnable' can only be used as a generic constraint because it has Self or associated type requirements
func get(_ type: Int) -> Runnable {
    if type= = 0 {return Person()
    }
    returnCar()} Func get1<T: Runnable>(_type: Int) -> T {
    if type= = 0 {return Person() as! T
    }
    returnCar() as! T} Solution two: use some func get2(_)type: Int) -> some Runnable {
    return Car()
}
Copy the code
Class Dog: Runnable {var speed: Int = 10} class Person {var pet: some Runnable {return Dog()
    }
}
Copy the code