Swift提供Error协议来表示当前应用程序发生的错误情况,Error的定义如下:
public protocol Error : Sendable {
}
所以Struct
、Class
、Enum
都可以通过遵守这个协议来表示一个错误,一般情况下偏向于用Enum
来表示错误。
1. 定义异常枚举
-
定义
enum JSONMapError: Error { case emptyKey // key为空 case notConformProtocol // 没有遵守协议 }
-
当需要抛出详细的错误信息时,可以让错误枚举遵守LocalizedError协议,协议内容如下:
public protocol LocalizedError : Error { /// A localized message describing what error occurred. var errorDescription: String? { get } /// A localized message describing the reason for the failure. var failureReason: String? { get } /// A localized message describing how one might recover from the failure. var recoverySuggestion: String? { get } /// A localized message providing "help" text if the user requests help. var helpAnchor: String? { get } }
示例:
extension JSONMapError: LocalizedError{ var errorDescription: String?{ switch self { case .emptyKey: return "key为空" case .notConformProtocol: return "没有遵守协议" } } }
-
当我们需要自定义错误信息的时候,可以让错误枚举类型遵守CustomNSError协议,协议内容如下:
public protocol CustomNSError : Error { /// The domain of the error. static var errorDomain: String { get } /// The error code within the given domain. var errorCode: Int { get } /// The user-info dictionary. var errorUserInfo: [String : Any] { get } }
示例:
extension JSONMapError: CustomNSError{ var errorCode: Int{ return 404 } }
2.错误的抛出
当需要抛出错误的时候,使用 throw 关键字将 Error 类型的错误抛出,同时使用throw关键字,则方法声明中就必须使用 throws 来接受错误,例如:
func test(name: String?) throws {
if name == nil {
throw JSONMapError.emptyKey
} else {
print("name不为空")
}
}
3.捕获错误
Swift中错误的集中处理方式:
- 使用try关键字
-
try
果发生错误,会向上层抛出,如果一直没有处理就会到main函数,还是没有处理就会崩溃 -
try?
返回的是一个可选类型,成功返回具体的值,错误则返回nil -
try!
确认不会有异常,如果有异常就直接崩溃
-
- 使用 do...catch
// 使用上面的例子演示错误的捕获
func testExample() {
//示例一
do {
try test(name: nil)
} catch {
let err = error as? LocalizedError
print(err?.errorDescription ?? "")
}
//示例2
do {
try test(name: nil)
} catch JSONMapError.emptyKey {
print("key为空")
}catch JSONMapError.notConformProtocol{
print("没有遵守协议")
} catch {
print("unKnown Error")
}
}
举个字典转模型中常见的错误捕捉例子
protocol CustomJSONMap{
func jsonMap() throws -> Any
}
extension CustomJSONMap{
func jsonMap() throws -> Any{
//Mirror反射,下个章节介绍
let mirror = Mirror(reflecting: self)
// 中断递归的条件
guard !mirror.children.isEmpty else {return self}
var keyValue: [String: Any] = [:]
for children in mirror.children{
if let value = children.value as? CustomJSONMap{
if let keyName = children.label {
keyValue[keyName] = try value.jsonMap() //递归调用
}else{
throw JSONMapError.emptyKey
}
}else{
throw JSONMapError.notConformProtocol
}
}
return keyValue
}
}
// 创建HJPerson并遵守CustomJSONMap协议
class HJPerson: CustomJSONMap{
var age = 18
var name = "寒冰射手"
var height = 1.85
}
// 需要遵守协议才能解析
extension Int: CustomJSONMap{}
extension String: CustomJSONMap{}
var p = HJPerson()
do{
try p.jsonMap()
}catch {
print("\(String(describing: (error as? LocalizedError)?.errorDescription))")
}
网友评论