使用 case :

为了能够记录错误,我们使它们符合特定的协议. 这似乎对自定义错误有效,然而,判断或将基础错误(如URLError)强制转换为此协议似乎失败了.

我不知道这里有什么不同.

在本例中:我们有一个视图模型,它执行可能导致错误的操作. 我们想用我们的记录器记录这个错误.

示例:


// Protocol that makes an error loggable

protocol LoggableError: Error {
    var message: String { get }
}

// Our custom error:

enum CustomError: Error {
    case someError
}

extension CustomError: LoggableError {
    var message: String {
        "Some error occurred"
    }
}

// URL error conforming to our LoggableError:

extension URLError: LoggableError {
    var message: String {
        "Some network error occurred"
    }
}

// The logger

protocol LoggerProtocol {
    func handle(error: some Error)
}

class Logger: LoggerProtocol {
    func handle(error: some Error) {
        guard let error = error as? LoggableError else { fatalError("Cast failed") }
        print(error.message)
    }
}

// The view model

class ViewModel {
    private let logger: LoggerProtocol

    init(logger: LoggerProtocol) {
        self.logger = logger
    }

    func doSomething() {
        do {
            try doSomethingDangerous()
        } catch {
            logger.handle(error: error)
        }
    }

    private func doSomethingDangerous() throws {
        throw CustomError.someError // this works
        // throw URLError(.notConnectedToInternet) // this triggers the fatalError
    }
}

// Trigger

let viewModel = ViewModel(logger: Logger())
viewModel.doSomething()

谁能告诉我我哪里做错了或者为什么这不管用? 经过7年的SWIFT开发,我似乎仍然不理解协议:D

推荐答案

首先,我认为这是Foundation中的一个错误,并建议打开一个关于它的反馈.但您遇到的问题是由于在Darwin上处理NSError的棘手方式(这就是为什么您在Linux上看不到这个问题).

许多基础错误实际上只是对NSError的包装.尽管他们有自己的SWIFT类型,但他们无法在存在主义的来回旅行中幸存下来:

print(type(of: CustomError.someError))              // CustomError
print(type(of: CustomError.someError as any Error)) // CustomError

print(type(of: URLError(.notConnectedToInternet)))              // URLError
print(type(of: URLError(.notConnectedToInternet) as any Error)) // **NSError**

(请注意,这与枚举和 struct 无关.如果将CustomError更改为 struct ,它仍然可以很好地工作.问题是您看不到的NSError.)

同样的问题也会发生在some点的时候.Objc和SWIFT类型最终不匹配.有一个神奇的桥梁基础错误,使他们更"迅速".但这是一个很有漏洞的抽象概念,这是一个错误.

如果可能,您应该使NSError符合LoggableError.这将解决这个问题.

Ios相关问答推荐

preferredCompactColumn作为NavigationSplitViewColumn.sidebar传递,但仍能在iOS上看到详细信息页面

一堆UIGraphics方法在iOS 17中被弃用,没有明确的替代方法?

用于HDR显示的CI上下文选项

如何在Swift中同时实现三个手势?

封装 Swift 导入

将 Riverpod 从 StateNotifier 修复为 NotifierProvider 以及应用程序生命周期监控

不使用故事板创建 iMessage 应用程序

核心媒体基础知识,了解 CMSampleBuffer、CMBlockBuffer 和 CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer

使用 Apollo 发布 iOS 应用程序时缺少推送通知权利

SwiftUI - 在ForEach的每个元素之间自动添加分隔符

UICollectionView - 水平滚动,水平布局?

实现一个将块用作回调的方法

如何判断 `NSManagedObject` 是否已被删除?

iOS 中是否有用于自定义振动的 API?

在 Swift 中将 HTML 转换为纯文本

在 iOS 8 中显示相机权限对话框

判断可选数组是否为空

为信用卡输入格式化 UITextField,例如 (xxxx xxxx xxxx xxxx)

我可以通过 UIAppearance 代理设置哪些属性?

在两个或多个 iPhone 应用程序之间共享数据