I don't really understand the difference between swift Error and NSError, so I tried to summarize it myself.

Introduction

I'm always developing with swift, but two error objects, Error and NSError, come out. What is it always divided by? I was wondering and typecasting from Error to NSError.

I thought that it would be bad for me if I didn't understand it well, so I thought I would leave it as a memorandum on Qiita.

What is the difference between Error and NSError?

What is the difference between the two in the first place?

When I look it up

-NSError is an error object of Objective-C and is defined as class.

-Error is an error object of swift and is defined as protocol.

It was that kind of feeling.

Let's take a closer look. NSError NSError is the error object used in Objective-C and contains information about the error state.

What kind of information is included It contains three pieces of information: domain, code, and userInfo.

I tried to summarize it for easy understanding ↓

information meaning
domain A string to identify the type of error
code An integer value to identify the type of error
userInfo Additional information about the error

Swift Error can always be cast to NSError, and you canreferencethe information.

When I actually write the code, it looks like this ↓

    func manager(error: Error) {
        //Cast from Error to NSError
        let nsError = error as NSError
        //Refer to the information you want
        print(nsError.domain)
        print(nsError.code)
        print(nsError.userInfo)
    }

For example, there is a delegate method for some manager class Suppose you have a method that will be called if an error occurs.

Then, the flow is to reference the information you want to cast the error to NSError.

What is the use of NSError?

In swift, it exists to maintain compatibility with Objective-C, but due to the strong error handling of swift, it seems that the opportunity to use the domain and code used in NSError has decreased. ..

However, if it is a project where two languages ​​are mixed, you will face a situation where you are aware of NSError.

I haven't touched Objective-C at all, so I don't know, but with the app I'm developing Since there are times when I want domain and code information, I cast it relatively.

Error As mentioned earlier, it is defined as the protocol in the error object used by swift.

Such swift Error is a protocol to show that a compliant type can be treated as a type expressing an error. There is no implementation required to comply.

In other words, Swift's Error is a protocol (protocol) that expresses error information.

By the way, as an aside, in swift2, Error was named Error Type. It seems that the name has changed from swift3 to Error.

What is the use of Error?

Types that conform to this Error protocol generally conform to enums. This is because it has the advantage of being able to describe all the errors that occur.

Moreover, without defining all possible errors throughout the program in a single enum. It seems that it is usual to define another type depending on the type of error.

Now, let's actually define an enumeration type according to the Error protocol.

This time, let's define the error that will occur when performing API communication with an enumeration type.

enum ApiError: Error {
    case networkError
    case decodeFailed
    case responceFailed
    case unknown
}

It can be defined like this.

After that, you can use it like this by giving it a argument. In the example below, the computed property is used to return a message for each case ↓

enum ApiError: Error {
    case networkError
    case decodeFailed(Error)
    case responceFailed(Error?)
    case unknown
    
    var message: String {
        switch self {
        case .networkError:
            return "A communication error has occurred"
            
        case .decodeFailed(let error):
            return "Decoding failed\(error.localizedDescription)"
        
        case .responceFailed(let error):
            return "Failed to get the response\(error?.localizedDescription ?? "error")"
            
        case .unknown:
            return "An unknown error has occurred"
        }
    }
}

let networkErrorMessage = ApiError.networkError.message
let decodeErrorMessage = ApiError.decodeFailed(error).message

If you want to get the error message from Error, you can use the localizedDescription property.

This property is originally defined by NSError, so it is not a property that Swift Error has, but it can be used by linking the Foundation framework.

The reason why it can be used is that the Foundation framework was originally made in Objective-C, and Objective-C used the NSError class included in the Foundation framework for error handling.

So, even in swift, if you import Foundation, you can use NSError class.

In addition, it is possible to have Int type and String type as arguments. You can represent information associated with an error.

enum DatabaseError {
    case networkError
    case invalidEntry(reson: String)
}

let invalidEntryReson = DatabaseError.invalidEntry(reson: "~Is invalid because of")

end

I tried to summarize the difference between Error and NSError. I've only touched swift, so it's a pretty swift-oriented article.

If there are any mistakes, I would appreciate it if you could comment.

Finally, the reference materials are listed below.

Reference material

Some experiments on Error and NSError in the Swift 3 era Introduction to Swift 4.0 Error Handling [Swift] I've summarized Swift's error handling roughly

Recommended Posts

I don't really understand the difference between swift Error and NSError, so I tried to summarize it myself.
I tried to summarize the basics of kotlin and java
[For Swift beginners] I tried to summarize the messy layout cycle of ViewController and View
Understand the difference between each_with_index and each.with_index
I didn't understand the topological sort, so I looked it up and implemented it in BFS, and then tried to solve the AtCoder problem.
I didn't understand the difference between Collections.emptyMap and Collections.EMPTY_MAP and my colleague got angry so I'll write it down here for self-discipline.
[Ruby] Maybe you don't really understand? [Difference between class and module]
I tried to summarize the methods of Java String and StringBuilder
I don't understand the devise_parameter_sanitizer method, so I'll output it here.
Easy to understand the difference between Ruby instance method and class method.
I tried to summarize the methods used
I tried to summarize the Stream API
[Java] Understand the difference between List and Set
Understand the difference between abstract classes and interfaces!
I built a CentOS 8 environment with Vagrant and tried to sync_folder, but I got an error, so I solved it.
[Java] I studied polymorphism, so I will summarize how to use it and its merits.
[Ruby] I thought about the difference between each_with_index and each.with_index
[Rails] I learned about the difference between resources and resources
I tried to summarize the state transition of docker
[Rails] I investigated the difference between redirect_to and render.
[Java beginner] Difference between length and length () ~ I don't know ~
Difference between i ++ and ++ i
[Rails 6.0, Docker] I tried to summarize the Docker environment construction and commands necessary to create a portfolio
Difference between Java and JavaScript (how to find the average)
[Swift] I tried to implement the function of the vending machine
I tried to summarize the basic grammar of Ruby briefly
I tried to summarize personally useful apps and development tools (development tools)
I tried to summarize personally useful apps and development tools (Apps)
The difference between programming with Ruby classes and programming without it
I tried to make it possible to set the delay for the UDP client of Android by myself
[Action View :: Missing Template] I didn't understand the meaning of the error statement, so I looked it up.
When I tried to run my own service, it failed, so I screwed it into the task scheduler
Memorandum: When I tried TensorFlow with Tribuo, it didn't work, so I went on a journey to find the head family and lost.
I tried to summarize the words that I often see in docker-compose.yml
I tried to summarize what was asked at the site-java edition-
[Ruby] Tonight, I tried to summarize the loop processing [times, break ...]
Special Lecture on Multi-Scale Simulation: I tried to summarize the 5th
I tried to translate the error message when executing Eclipse (Java)
I tried to understand how the rails method "redirect_to" is defined
I tried to understand how the rails method "link_to" is defined
Special Lecture on Multi-Scale Simulation: I tried to summarize the 7th
[Rails] I tried to summarize the passion and functions of the beginners who created the share house search site!
I tried to summarize iOS 14 support
I tried to explain the method
I tried to summarize Java learning (1)
I tried to understand nil guard
I tried to summarize Java 8 now
I tried to summarize the stumbling points when developing an Android application
[Introduction to Java] I tried to summarize the knowledge that I think is essential
Don't forget to summarize the features and points of the flea market apps
[Ruby] I tried to summarize the methods that frequently appear in paiza
I tried to figure out the relationship between classes such as java.io.InputStream
[Rails] I studied the difference between new method, save method, build method and create method.
[Ruby] I tried to summarize the methods that frequently appear in paiza ②
Understand the difference between int and Integer and BigInteger in java and float and double
I tried to measure and compare the speed of GraalVM with JMH
Delegated type added in Rails 6.1 and Union types of GraphQL seem to be compatible, so I tried it