This is a study note, the handling of errors and exceptions in my own code is rather poor… However, Swift has some error handling mechanisms, so it keeps a written record of its own learning.

3. Objc.cn ####3.Swift Progression (updated to Swift 3.0)

###1. What are exceptions and errors? Exceptions are in our everyday coding, and anything that causes a program to fail can be called an exception. For example, sending a message to an unresponsive object or accessing more than the array element subscript will generate exceptions, resulting in APP crash. Errors are reasonable problems that may exist, such as login errors or some API errors. However, NSErrorPointer is passed in OC to store error information, but I personally usually pass a nil….

###2. What new changes does Swift bring? After Swift2.0, the language introduced exceptions, and apis with NSError became apis that could throw exceptions.

public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
Copy the code

Methods containing throws an exception, while REthrows does the same thing as throws. Rethrows are generally used in methods containing parameters, as shown above. The map function can take either a transform function or a function that throws an exception.

Let me post my modified login feature: ####1. Define an Enum to represent an Error type. It complies with Error Protocol (Swift3)(ErrorType Swift2).

enum LoginError: Error {
    caseErrorPassword(Int) // The password is incorrectcaseUserNotFound // Account error}Copy the code

####2. Then start writing the logon method, which throws exceptions. Throw throws after the function declaration:

func login(user: String, password: String) throws {
    ifuser ! ="admin"{throw loginerror. UserNotFound // throw an exception}ifpassword ! ="password"{throw loginerror.errorPassword (404) // throw an exception}print("login success"// Login succeeded}Copy the code

####3. Use the try keyword before calling a method that will throw an exception. If you want to catch an exception thrown, you need to put the code that will throw the exception in the code block that do contains; The catch keyword is used to match various exceptions that need to be caught.

do {
    try login(user: "admina", password: "password")
} catch LoginError.UserNotFound {
    print("UserNotFound")
} catch let LoginError.ErrorPassword(errorCode) {
    print("ErrorPassword")
    print(errorCode)
}

//log: UserNotFound
Copy the code

If you are sure that the function call will not raise an exception, you can use try! To call:

try! login(user: "admina", password: "password")
Copy the code

This way, you don’t have to put the code block inside the do catch code block, but if the call throws an exception,Swift will raise a runtime exception. Error types combined with generics or login modules, if you treat the result and error exceptions as a single type, and then treat success and error as two different cases, then:

enum LoginResult<T> {
    case success(T)
    case failure(String)
}
Copy the code

Use a generic enum to represent the result returned, with type T in success and String in failure, which returns the reason for the failure.

func userLogin<T>(user: String, password: String) -> LoginResult<T> {
    ifuser ! ="admin" {
        return LoginResult<T>.failure("error userName")}ifpassword ! ="password" {
        return LoginResult<T>.failure("error password")
    }
    guard let value = "login success" as? T else {
        return LoginResult<T>.failure("some error")}return LoginResult<T>.success(value)
}
Copy the code

The logon function can then return an enum with a generic type, which can unify the result.

let result: LoginResult<String> = userLogin(user: "admin", password: "password")

switch result {
case .success(let result):
    print(result)
case .failure(let errorMessage):
    print(errorMessage)
}
Copy the code

In Swift programming, because of the unique nature of Swift, it is best not to ignore error types. Throws throws and combines generics TO make our code elegant and secure. //:TO DO(XXX)