Swift 3 Errors with Additional Data

Swift 3 errors with additional data

I don't know if there is a "recommended" way, perhaps someone else can
answer that or provide a better solution.

But one possible approach would be to use a struct (with properties) as the error type and use optional properties for values which need
not be provided. Example:

struct ParserError: Error {
enum Reason {
case invalidCharacter
case unexpectedEOF
}
let reason: Reason
let line: Int?
let column: Int?

init(reason: Reason, line: Int? = nil, column: Int? = nil) {
self.reason = reason
self.line = line
self.column = column
}
}

One might also want to adopt the LocalizedError protocol to
provide sensible error descriptions even if the
concrete error type is not known by the catcher (compare How to provide a localized description with an Error type in Swift?):

extension ParserError: LocalizedError {
public var errorDescription: String? {
var description: String
switch reason {
case .invalidCharacter:
description = "Invalid Character in input file"
case .unexpectedEOF:
description = "Unexpected end of file"
}
if let line = line {
description += ", line \(line)"
}
if let column = column {
description += ", column \(column)"
}
return description
}
}

Usage example:

func parse() throws {
// Throw error with line number, but without column:
throw ParserError(reason: .invalidCharacter, line: 13)
}

do {
try parse()
} catch let error {
print(error.localizedDescription)
}

Output:


Invalid Character in input file, line 13

Swift Error Handling and metadata of the error

If you would like to access the description property of networkError case , you do not need to do too much.

func feedFinishedParsing(withFeedArray feedArray: [FeedItem]?, error: AnnouncerError?) {
// unwrap the error somewhere here
switch error {
// Just declare description in the case, and use it if u need it.
case .networkError(let description):
print("Network error occured")
print(description)
case .parseError:
print("Parse error occured")
case .unwrapError:
print("Unwrap error occured")
default:
print("Unknown error occured")
}
}

Of course, you can build a robust machine for error handling, but if you just wanna access this property, the above solution will do the trick.

Regardless, i would recommend to read further into Swift pattern matching, what explains in detail the advanced usage of the switch language element is Swift.

Confused on Error Handling in Swift 3

As a general rule, try avoiding using force unwrapping (!), where you have

if let _: String= try! data.substring...

Instead use

if let index = data.index(of: "var sources2"), 
let _: String = try? data.substring(from: index) { ... } else { ... }

That way you remove the two force unwraps that may be causing your crash. You already have the if let protection for catching the nil value, so you can make the most of it by using the conditional unwrapping.

Swift 3: 'if let' optional binding error

try doesn't return an optional. try? does.

What are all types may be used as errors in Swift?

Any type conforming to the Error protocol can be used. If you really want
to throw an array then it suffices to declare conformance to the protocol:

extension Array: Error {}

do {
throw [1, 2, 3]
} catch {
print("Failed:", error) // Failed: [1, 2, 3]
}

Here is more realistic example, using a struct to throw
an error with additional information (a simplified example from
Swift 3 errors with additional data):

struct ParserError: Error, LocalizedError {
let line: Int

public var errorDescription: String? {
return "Parser error at line \(line)"
}
}

func parse() throws {
throw ParserError(line: 13)
}

do {
try parse()
} catch let error {
print(error.localizedDescription)
}

Output:

Parser error at line 13


Related Topics



Leave a reply



Submit