Skip to content

Instantly share code, notes, and snippets.

@acerosalazar
Last active July 16, 2018 16:52
Show Gist options
  • Save acerosalazar/4ca8d1596f1e3eceaf4d6c7099961cb9 to your computer and use it in GitHub Desktop.
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
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