Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

Error handling

To make our own wrapped JSON parsing work, we need to handle errors in addition to normal returns. How to express errors in Swift? First of all, Swift provides the Error protocol to identify the current application Error situation, where Error is defined as follows

public protocol Error {
}
Copy the code

Error is an empty protocol with no implementation, which means you can follow the protocol and then customize the Error type. So whether it’s our struct, Class, enum, we can follow this Error to indicate an Error

So next, modify the error handling in the JSON parsing we encapsulated above

  • To define aJSONMapErrorError enumeration, replacing the default implementation of print with an enumeration type
// Define error type enum JSONMapError: Error{case emptyKey case notConformProtocol} protocol CustomJSONMap {func jsonMap() -> Any} //2, provide a default implementation of extension CustomJSONMap{func jsonMap() -> Any{let mirror = mirror (reflecting: self) 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 {// Recursive keyValue[keyName] = value.jsonmap ()}else{return JSONMapError.emptyKey } }else{ return JSONMapError.notConformProtocol } } return keyValue } }Copy the code

But there is a problem. The jsonMap method returns Any, and we can’t tell whether we are returning an error or json data, so how can we tell? How do you throw an error? You can use the throw keyword here.

//2, provide a default implementation of extension CustomJSONMap{func jsonMap() -> Any{let mirror = mirror (reflecting: self) 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 {// Recursive keyValue[keyName] = value.jsonmap ()}else{throw JSONMapError.emptyKey } }else{ throw JSONMapError.notConformProtocol } } return keyValue } }Copy the code
  • The compiler prompts an error when changing the method to throw because the method was not declaredthrows

  • So you also need to increment it before the return value arrow of the methodthrows(represents throwing errors in methods), the modified default implementation code is shown below
Protocol CustomJSONMap{func jsonMap() throws-> Any} extension CustomJSONMap{func} JsonMap () throws -> Any{let mirror = mirror (reflecting: self) 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 {// Recursive keyValue[keyName] = value.jsonmap ()}else{throw JSONMapError.emptyKey } }else{ throw JSONMapError.notConformProtocol } } return keyValue } }Copy the code
  • Since we recursively called ourselves in the jsonMap method, we also need to increment before the recursive calltryThe keyword
Throw extension CustomJSONMap{func jsonMap() throws -> Any{let mirror = mirror (reflecting: Self) // Recursive terminating condition 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 {// Recursive keyValue[keyName] = try value.jsonmap ()}else{throw JSONMapError.emptyKey } }else{ throw JSONMapError.notConformProtocol } } return keyValue } } <! Var t = CJLTeacher() print(try t.jsonmap)Copy the code

At this point, a complete error representation is complete