SwiftUI自定义错误附加追踪详情的标准实现方案问询
解决Swift自定义错误携带额外排查信息的方案
针对你需要在自定义错误中保存额外技术细节(比如解码缺失的key、上下文),同时给用户展示简洁提示的需求,有两种标准且实用的解决方式:
1. 给自定义错误枚举添加关联值(最常用)
Swift枚举支持关联值,刚好可以用来存储错误的额外细节,而且避开了“扩展不能添加存储属性”的限制——因为关联值是枚举本身的特性。
修改自定义错误枚举
把原来的apiDecodingError改成带关联值的case,用来保存解码错误的关键信息:
enum CustomError: Error { // 带关联值存储解码错误的具体信息 case apiDecodingError(missingKey: String, context: DecodingError.Context) // 其他业务错误case示例 case networkError(message: String) }
扩展LocalizedError提供用户友好提示
保持扩展只负责返回用户可见的简洁提示,不处理技术细节:
extension CustomError: LocalizedError { var errorDescription: String? { switch self { case .apiDecodingError: return NSLocalizedString("Problem understanding service response.", comment: "") case .networkError(let message): return NSLocalizedString(message, comment: "") // 其他错误case的提示逻辑... } } }
捕获原始错误并抛出自定义错误
在解码失败的场景,把原始错误的信息通过关联值传入自定义错误:
do { let decodedData = try JSONDecoder().decode(YourModel.self, from: responseData) } catch let DecodingError.keyNotFound(key, context) { // 将缺失的key和上下文存入自定义错误 throw CustomError.apiDecodingError(missingKey: key.stringValue, context: context) } catch { throw CustomError.networkError(message: "Network request failed") }
捕获自定义错误并提取技术细节上报
在最终的错误处理逻辑中,通过switch判断错误类型,取出关联值用于bug追踪:
do { try performAPIRequest() } catch { // 给用户展示错误提示 isAlertErrorPresented = true errorAlert = ErrorAlert(error: error) // 提取技术细节上报到bug追踪系统 var trackingProperties = ["Error": error.localizedDescription] if let customError = error as? CustomError { switch customError { case .apiDecodingError(let missingKey, let context): trackingProperties["MissingKey"] = missingKey trackingProperties["DebugDescription"] = context.debugDescription trackingProperties["CodingPath"] = context.codingPath.map { $0.stringValue }.joined(separator: ".") case .networkError(let message): trackingProperties["NetworkMessage"] = message // 处理其他错误case... } } Analytics.trackEvent("UpdateNotificationSetting", withProperties: trackingProperties, flags: .critical) }
2. 通用错误包装器(适合多类型错误统一处理)
如果你的项目中有多种原始错误需要包装,也可以创建一个通用的错误包装结构体,实现Error和LocalizedError协议,统一存储原始错误、用户提示和额外技术信息:
struct WrappedError: LocalizedError { let userMessage: String let originalError: Error? let technicalDetails: [String: Any]? var errorDescription: String? { return userMessage } }
使用方式:包装原始错误
在捕获原始错误时,将其包装成WrappedError:
catch let DecodingError.keyNotFound(key, context) { let technicalDetails: [String: Any] = [ "MissingKey": key.stringValue, "DebugDescription": context.debugDescription, "CodingPath": context.codingPath.map { $0.stringValue }.joined(".") ] throw WrappedError( userMessage: NSLocalizedString("Problem understanding service response.", comment: ""), originalError: error, technicalDetails: technicalDetails ) }
处理包装后的错误
catch let wrappedError as WrappedError { isAlertErrorPresented = true errorAlert = ErrorAlert(error: wrappedError) var trackingProperties = ["Error": wrappedError.userMessage] if let details = wrappedError.technicalDetails { properties.merge(details) { $1 } } Analytics.trackEvent("UpdateNotificationSetting", withProperties: trackingProperties, flags: .critical) }
这两种方案都是Swift生态中处理这类需求的标准做法:第一种更适合针对特定业务错误做定制,第二种更适合统一管理所有错误的额外信息。
内容的提问来源于stack exchange,提问作者lcj
相关产品推荐
相关产品推荐

