🥱 减少 do ... try ... catch 的冗余。
旧方式
func parse(url: String) throws -> String {
guard let url = URL(string: url) else {
throw ParserError.invalidURL
}
do {
return try String(contentsOf: url)
} catch {
throw ParserError.invalidWebpage
}
}
新方式
func parse(url: String) throws -> String {
guard let url = URL(string: url) else {
throw ParserError.invalidURL
}
return try execute(String(contentsOf: url),
orThrow: Error.invalidWebpage)
}
execute
方法有三种重载
execute( _: ,orThrow:)
execute( _: ,errorTransform:)
execute( _: ,orCaptureError:)
你经常会发现自己在做这些
func signup(user: User) {
guard user.username.count >= 3 else {
errorLabel.text = "Username must have at least 3 characters"
return
}
guard user.password.count >= 7 else {
errorLabel.text = "Password must have at least 7 characters"
return
}
// Additional validation like email ...etc
...
authService.signup(user: user) { result in
...
}
}
验证逻辑最终可能比我们预期的增长得更快,因此 Validator
派上用场。
我们可以通过扩展 Validator
来简单地添加我们的自定义验证逻辑,如下所示
extension Validator where Value == String {
static var password: Validator {
return Validator { string in
try validate(
string.count >= 7,
errorMessage: "Password must contain min 7 characters"
)
// you can add more logig here...
try validate(
string.uppercased() != string,
errorMessage: "Password must contain a lowercased character"
)
}
}
static var username: Validator {
return Validator { string in
try validate(string.count >= 3, errorMessage: "Username must have at least 3 characters")
}
}
}
然后我们可以使用全新的验证器简化我们的注册方法
func signup(user: User) throws {
try validate(user.username, using: .username)
try validate(user.password, using: .password)
authService.signup(user: user) { result in
...
}
}
现在调用该函数
try! execute(signup(user: user)) {
self.errorLabel.text = $0.localizedDescription
}
任何符合此协议的 Error
类型都必须实现类型为 ErrorCategory
的 category
属性
例子
enum NetworkError: Error {
case noInternetConnection
case decodingFailure
case notAuthorized
}
extension NetworkError: CategorizedError {
var category: ErrorCategory {
switch self {
case .noInternetConnection:
return .retryable
case .decodingFailure:
return .notRetryable
case .notAuthorized:
return .requiresLogin
}
}
}
现在我们可以很容易地例如根据错误类型显示或隐藏重试按钮。
func handle(error: Error) {
// do other stuff
switch error.resolveCategory() {
case .retryable:
break
case .notRetryable:
retryButton.isHidden = true
case .requiresLogin:
performLogin()
}
}
例如
var path: String?
...
func save() throws {
let path = path.orThrow(Error.invalidPath)
}
ErrorUtils
可通过 CocoaPods 获得。要安装
它,只需将以下行添加到你的 Podfile 中
pod 'ErrorUtils'
Carthage 是一个去中心化的依赖管理器,它构建你的依赖项并为你提供二进制框架。
要使用 Carthage 将 ErrorUtils 集成到你的 Xcode 项目中,请在你的 Cartfile
中指定它
github "engali94/ErrorUtils"
运行 carthage update
来构建框架,并将构建的 ErrorUtils.framework
拖到你的 Xcode 项目中。
在你的应用程序目标的 “Build Phases” 设置选项卡中,单击 “+” 图标并选择 “New Run Script Phase”,然后按照 Carthage 入门步骤 4、5 和 6 中的说明添加框架路径
要使用 Apple 的 Swift Package Manager 进行集成,请将以下内容作为依赖项添加到你的 Package.swift
中
dependencies: [
.package(url: "https://github.com/engali94/ErrorUtils.git", from: "1.0.0")
]
或者,导航到你的 Xcode 项目,选择 Swift Packages
并单击 +
图标以搜索 ErrorUtils
。
如果你不想使用任何上述依赖管理器,你可以手动将 ErrorUtils
集成到你的项目中。 只需将 Sources
文件夹拖到你的 Xcode 项目中即可。
非常欢迎贡献 🙌
这里完成的大部分工作都受到 Swiftbysundell 文章的启发。
ErrorUtils 在 MIT 许可证下发布。 有关更多信息,请参见 LICENSE。