Swift捕获特定错误类型时,如何同时获取error实例?
Swift错误处理:同时获取关联值与错误本身的优雅方案
最让人头疼的莫过于本以为两分钟就能搞定的简单事,最后花了一个多小时!🤦🏻
编写单元测试时,我们需要测试多种带关联值的特定错误类型,同时还要访问错误本身,用来测试本地化描述。但常规的模式匹配虽然能拿到关联值,却没法直接访问错误实例来获取localizedDescription这类属性。
示例错误类型
public enum MyError: LocalizedError { case missingKey(in: String, at: String.Index) public var errorDescription: String { "I Need To Get This Too" } }
常规模式匹配的局限
下面的代码能通过模式匹配拿到关联值,但catch块里没法访问错误本身,也就没法检查本地化描述:
do { throw MyError.missingKey(in: "A", at: "A".startIndex) } catch let MyError.missingKey(in: string, at: location) { // 拿到了关联值string和location,但怎么获取本地化描述? print(string, location) } catch let otherErr { print(otherErr) }
不推荐的“万能catch”方案
你可以用全局catch配合内部switch来实现需求,但这种做法不推荐——它会捕获所有意外错误,迫使你在代码块内处理所有情况,容易导致职责混乱:
do { throw MyError.missingKey(in: "A", at: "A".startIndex) } catch { switch error { // 处理特定错误 case let MyError.missingKey(in: string, at: location): print(string, location, error.localizedDescription) // 终于能拿到了! case let otherErr: print(otherErr) default: throw error } }
更优雅的解决方案
方案1:同时绑定错误实例与关联值
Swift支持在catch中同时捕获错误实例并匹配特定关联值模式,既精准又安全:
do { throw MyError.missingKey(in: "A", at: "A".startIndex) } catch let error as MyError, case .missingKey(in: let string, at: let location) { // 同时拿到错误实例和关联值 print(string, location, error.localizedDescription) } catch let otherErr { print(otherErr) }
这种方式只会捕获MyError类型的指定case,不会意外拦截其他错误,同时保留了对错误实例的访问权限。
方案2:先转类型再内部匹配
如果需要处理同一个错误类型的多个case,可以先将错误转为对应类型,再在内部做switch匹配:
do { throw MyError.missingKey(in: "A", at: "A".startIndex) } catch let error as MyError { switch error { case .missingKey(in: let string, at: let location): print(string, location, error.localizedDescription) // 可以在这里添加MyError其他case的处理逻辑 } } catch let otherErr { print(otherErr) }
这种方式同样能保证错误捕获的精准性,同时在内部可以自由访问错误实例和对应case的关联值。
内容的提问来源于stack exchange,提问作者Mark A. Donohoe
相关产品推荐
相关产品推荐

