Skip to content

Commit

Permalink
Minor tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed May 19, 2022
1 parent 42e1195 commit 325841f
Showing 1 changed file with 56 additions and 6 deletions.
62 changes: 56 additions & 6 deletions Blear/Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -724,28 +724,68 @@ extension Dictionary {
}


extension NSObject {
// Note: It's intentionally a getter to get the dynamic self.
/**
Returns the class name without module name.
*/
static var simpleClassName: String { String(describing: self) }

/**
Returns the class name of the instance without module name.
*/
var simpleClassName: String { Self.simpleClassName }
}


extension Error {
var isNsError: Bool { Self.self is NSError.Type }
/**
Whether the error matches the given domain and code.
*/
func matches(domain: String, code: Int) -> Bool {
let nsError = self as NSError
return nsError.domain == domain && nsError.code == code
}

/**
Whether the error or any of its underlying errors match the given domain and code.
*/
func matchesDeep(domain: String, code: Int) -> Bool {
let nsError = self as NSError

return matches(domain: domain, code: code)
|| nsError.underlyingErrors.contains { $0.matches(domain: domain, code: code) }
}
}


extension Error {
/**
Whether the error was originally created as an `NSError`.
*/
var isNSError: Bool {
// This used to work before Swift 5.6:
// `var isNsError: Bool { Self.self is NSError.Type }``
(self as NSError).simpleClassName != "__SwiftNativeNSError"
}
}

extension NSError {
static func from(error: Error, userInfo: [String: Any] = [:]) -> NSError {
let nsError = error as NSError

// Since Error and NSError are often bridged between each other, we check if it was originally an NSError and then return that.
guard !error.isNsError else {
guard !error.isNSError else {
guard !userInfo.isEmpty else {
return nsError
}

return nsError.appending(userInfo: userInfo)
}

var userInfo = userInfo
var userInfo = nsError.userInfo.appending(userInfo)
userInfo[NSLocalizedDescriptionKey] = error.localizedDescription

// Awful, but no better way to get the enum case name.
// This gets `Error.generateFrameFailed` from `Error.generateFrameFailed(Error Domain=AVFoundationErrorDomain Code=-11832 […]`.
let errorName = "\(error)".split(separator: "(").first ?? ""

return .init(
Expand Down Expand Up @@ -880,6 +920,7 @@ extension CGImage {
let source = CGImageSourceCreateWithURL(url as CFURL, sourceOptions as CFDictionary),
let image = CGImageSourceCreateThumbnailAtIndex(source, 0, thumbnailOptions as CFDictionary)
else {
_ = try Data(contentsOf: url, options: [.uncached]) // Just to get a better error.
throw NSError.appError("Failed to load image.")
}

Expand Down Expand Up @@ -953,8 +994,17 @@ extension NSItemProvider {
func loadFileRepresentation(for type: UTType) async throws -> URL {
try await withCheckedThrowingContinuation { continuation in
_ = loadFileRepresentation(forTypeIdentifier: type.identifier) { url, error in
if let error = error {
if var error = error {
// Error Domain=CloudPhotoLibraryErrorDomain Code=82 "Failed to download CPLResourceTypeOriginal"
if error.matchesDeep(domain: "CloudPhotoLibraryErrorDomain", code: 82) {
error = NSError.appError(
"Failed to download photo from iCloud.",
recoverySuggestion: "Make sure you are connected to the internet."
)
}

continuation.resume(throwing: error)

return
}

Expand Down

0 comments on commit 325841f

Please sign in to comment.