admin 管理员组

文章数量: 1184232

Swift Runtime探索,Error定义使用

我们⽤下⾯这段代码来测试⼀下:

class LGTeacher { 
 var age: Int = 18 
 func teach(){ 
   print("teach") 
 }  
} 
 let t = LGTeacher() 
 func test(){ 
     var methodCount:UInt32 = 0 
     let methodlist = class_copyMethodList(LGTeacher.self, &method Count) 
     for i in 0..<numericCast(methodCount) { 
         if let method = methodlist?[i]{ 
             let methodName = method_getName(method); 
             print("⽅法列表:\(String(describing: methodName))") 
         }else{ 
             print("not found method"); 
         } 
     } 
     var count:UInt32 = 0 
     let proList = class_copyPropertyList(LGTeacher.self, &count) 
     for i in 0..<numericCast(count) {
         if let property = proList?[i]{
             let propertyName = property_getName(property);
             print("属性成员属性:\(String(utf8String: propertyName)! )")
         }else{
             print("没有找到你要的属性"); 
         } 
     } 
 }

运⾏这段代码你会发现,当前不管是我们的⽅法列表还是我们的属性列表,此次此刻都是为空的。

@objc 的标识,如果这个时候我们将我们当前的⽅法和属性添加上,会发⽣什么?

2. 反射

反射就是可以动态获取类型、成员信息,在运⾏时可以调⽤⽅法、属性等⾏为的特性。上⾯我们分析过 了,对于⼀个纯 Swift 类来说,并不⽀持我们直接像 OC 那样操作;但是 Swift 标准库依然提供了反射机制让我们访问成员信息, 反射的⽤法⾮常简单,我们⼀起来熟悉⼀下:

     var t = LGTeacher()
     let mirror = Mirror(reflecting: t) 
     for pro in mirror.children{ 
     print("\(pro.label):\(pro.value)") 
 }

那这个时候我们能⽤ Mirror 做些什么事情那?⾸先想到的应该就是 JSON 解析了:

func test(_ obj: Any) -> Any { 
    let mirror = Mirror(reflecting: obj)
    guard !mirror.children.isEmpty else {return obj}
    var keyValue: [String: Any] = [:]
    for children in mirror.children{
         if let keyName = children.label {
             keyValue[keyName] = test(children.value)
         }else{
             print("children.label 为空")
         }
     }
     return keyValue
 }

上述代码中我们虽然完成了⼀个简单的 JSON 解析的Demo ,但是很多错误都是输出,如何在 Swift 中专业的表达错误那?

3. 错误处理

Swift 提供 Error 协议来标识当前应用程序发生错误的情况,error 的定义如下:

 public protocol Error{ 
 }

所以不管是我们的 struct Class enum 我们都可以通过遵循这个协议来表示⼀个错误。这⾥我们选择 enum

 enum JSONMapError: Error { 
     case emptyKey 
     case notConformProtocol  
}

但是这⾥我们使⽤ return 关键字直接接收了⼀个 Any 的结果,如何抛出错误,正确的⽅式是使⽤ throw 关键字。 于此同时,编译器会告诉我们当前的我们的 function 并没有声明成 throws ,所以修改代码之后就能得出这样的结果了:

enum JSONMapError: Error { 
    case emptyKey 
    case notConformProtocol 
}
protocol CustomJSONMap { 
    func jsosnMap() thorws -> Any 
}
extension CustomJSONMap{
     func jsonMap() throws -> Any{
         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
     }
 }

我们来使⽤⼀下我们当前编写完成的代码,会发现编译器要求我们使⽤ try 关键字来处理错误。接下来我们就来说⼀说 Swift 中错误处理的⼏种⽅式:

  • 使⽤ try 关键字,是最简便的,也是我们最喜欢的:甩锅

如何你觉得仅仅使⽤ Error 并不能达到你想要详尽表达错误信息的⽅式,可以使⽤ LocalError 协议 , 定义如下:

public protocol LocalizedError : Error {
 /// A localized message describing what error occurred. 
 var errorDescription: String? { get }
 /// A localized message describing the reason for the failur e. 
 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 req uests help.
 var helpAnchor: String? { get }
}

CustomError 有三个默认属性:

  1. a static errorDomain
  2. an errorCode integer
  3. an errorUserInfo dictionary

本文标签: 是我们的 我们 这段代码