Last active
July 16, 2018 16:52
-
-
Save acerosalazar/4ca8d1596f1e3eceaf4d6c7099961cb9 to your computer and use it in GitHub Desktop.
A set of extensions for NSError to make it easy to create and manage nested NSErrors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
// MARK: - | |
extension NSError { | |
func contains(domain: String, code: Int, checkUnderlyingErrors: Bool = true) -> Bool { | |
return first(withDomain: domain, code: code, checkUnderlyingErrors: checkUnderlyingErrors) != nil | |
} | |
func first(withDomain domain: String, code: Int, checkUnderlyingErrors: Bool = true) -> NSError? { | |
guard self.domain != domain || self.code != code else { return self } | |
guard checkUnderlyingErrors else { return nil } | |
guard let underlyingError = userInfo[NSUnderlyingErrorKey] as? NSError else { return nil } | |
return underlyingError.first(withDomain: domain, code: code, checkUnderlyingErrors: checkUnderlyingErrors) | |
} | |
func appending(error: Error) -> NSError { | |
var userInfo = self.userInfo | |
userInfo[NSUnderlyingErrorKey] = error as NSError | |
return NSError(domain: domain, code: code, userInfo: userInfo) | |
} | |
override open var debugDescription: String { | |
func errorList(for error: NSError) -> [NSError] { | |
if let underlyingError = error.userInfo[NSUnderlyingErrorKey] as? NSError { | |
return [error] + errorList(for: underlyingError) | |
} else { | |
return [error] | |
} | |
} | |
func errorDescription(for error: NSError) -> String { | |
var redactedUserInfo = error.userInfo | |
redactedUserInfo[NSUnderlyingErrorKey] = nil | |
return "domain: \(error.domain), code: \(error.code), userInfo: \(redactedUserInfo)" | |
} | |
let errors = errorList(for: self) | |
return zip(errors, 0..<errors.count).reduce("\n") { acc, elem in | |
let (error, level) = elem | |
return "\(acc)\(String(repeating: "\t", count: level)) – \(errorDescription(for: error))\n" | |
} | |
} | |
} | |
// MARK: - | |
typealias ErrorMatcher = (domain: String, code: Int) | |
func ~= (pattern: ErrorMatcher, value: NSError) -> Bool { | |
return value.contains(domain: pattern.domain, code: pattern.code) | |
} | |
// MARK: - | |
extension CustomNSError { | |
var matcher: ErrorMatcher { | |
return ErrorMatcher(domain: Self.errorDomain, code: errorCode) | |
} | |
static func matcher(withCode code: Int) -> ErrorMatcher { | |
return ErrorMatcher(domain: Self.errorDomain, code: code) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment