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 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 canreference
the 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
.
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
.
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")
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.
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