我正在参与「启航方案」
本文主要对Swift的反射完成有一个根本的知道,经过JSON解析来知道反射以及过错的实际运用。
主要内容
- Mirror的运用
- 过错Error的运用
1、 Mirror
Swift是一门静态言语,没有像OC中Runtime那样的运行时操作。但是Swift标准库中供给了反射机制,用来动态访问成员信息,这就是Mirror。(当然远没有Runtime那样强壮)
1.1 根本运用
代码:
/*
1、运用
*/
class WYTeacher: NSObject {
var age: Int = 18
}
var t = WYTeacher()
let mirror = Mirror(reflecting: t.self)
for pro in mirror.children{
print("\(String(describing: pro.label)): \(pro.value)")
}
//Optional("age"): 18
阐明:
- 传入的是一个目标
- 获取到MIrror目标,经过它就能够获取到t目标的成员,别离经过label、value获取特点和值
1.2 Mirror知道
Mirror的初始化:
public init(reflecting subject: Any)
阐明:
- 进入Mirror初始化办法,发现传入的类型是Any,
- 正是这个原因,我们才能够直接传t
- 创立在给定实例上进行反射的反射目标
- 假如subject的类型恪守CustomReflectable协议,生成的mirror由customMirror特点决定
children
public let children: Mirror.Children
//进入Children,发现是一个AnyCollection,接纳一个泛型
public typealias Children = AnyCollection<Mirror.Child>
//进入Child,发现是一个元组类型,由可选的标签和值构成,
public typealias Child = (label: String?, value: Any)
阐明:
- children的类型为Children
- 而Children是AnyCollection<Mirror.Child>的别号,是一切Child的集合
- Child又是一个元组,由label、value组成
- 别离用来存储特点和值
2、JOSN的完成
经过反射能够很轻松的获取到一个目标的成员,因而我们能够用来进行JSON解析,将一个目标转换成JSON格局
代码:
/*
2、JSON解析
*/
//Int、String恪守协议
extension Int: CustomJSONMap{}
extension String: CustomJSONMap{}
//1、界说一个JSON解析协议
protocol CustomJSONMap {
func jsonMap() -> Any
}
//2、供给一个默许完成
extension CustomJSONMap{
func jsonMap() -> Any{
let mirror = Mirror(reflecting: self)
//递归停止条件
guard !mirror.children.isEmpty else {
return self
}
//字典,用于存储json数据
var keyValue: [String: Any] = [:]
//遍历
for children in mirror.children {
if let value = children.value as? CustomJSONMap {
if let keyName = children.label {
//递归
keyValue[keyName] = value.jsonMap()
}else{
print("key是nil")
}
}else{
print("当时-\(children.value)-没有恪守协议")
}
}
return keyValue
}
}
//3、让类恪守协议(注意:类中特点的类型也需求恪守协议,否则无法解析)
class WYTeacher: CustomJSONMap {
var age = 18
var name = "WY"
}
//运用
var t = WYTeacher()
print(t.jsonMap())
阐明:
- 专门界说一个用来进行JSON解析的协议,这样能够给你恣意类型的目标进行解析,只需求这个类型恪守该协议即可
- 这儿的完成也就是拿到目标的成员,别离存储到字典中,之后返回
- 这儿进行了递归调用,由于有可能特点本身也是一个目标。以一个字典的方式再存储到这个key的value上
- 类中特点的类型也需求恪守协议,由于这儿涉及到递归调用
3、Error的运用
在上文对于过错的处理是仅仅进行打印,这样并不规范,Swift中也供给了Error的处理方式。
Error的知道能够看我的另一篇博客Swift语法(十)Error
3.1 Error
Swift中,供给了Error协议来标识当时应用程序发生过错的状况。struct、Class、enum都能够恪守该协议,自界说过错。
代码:
//界说过错类型
enum JSONMapError: Error{
case emptyKey
case notConformProtocol
}
protocol CustomJSONMap {
func jsonMap() throws -> Any
}
//2、供给一个默许完成
extension CustomJSONMap{
func jsonMap() throws -> Any{
let mirror = Mirror(reflecting: self)
//递归停止条件
guard !mirror.children.isEmpty else {
return self
}
//字典,用于存储json数据
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
}
}
var t = WYTeacher()
print(try t.jsonMap())
阐明:
- 界说一个Error的枚举
- 能够运用throw抛出异常
- 办法中经过throws将过错抛出
- 可能抛出异常的函数需求运用try调用,防止编译报错
- 但是仅仅运用try调用,没有进行处理,这样会闪退
- 能够运用try … catch进行过错处理。详细的处理能够看另一篇博客,这儿不再赘述
3.2 LocalError协议
假如仅仅用Error还不足以表达更翔实的过错信息,能够运用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 }
}
阐明:
- LocalError协议供给了多种特点
- 我们能够给协议的这些特点添加描绘,这样在过错处理时就能够进行打印
运用: 此刻不给Int和String恪守CustomJSONMap,因而会走.notConformProtocol的分支
//界说更详细的过错信息
extension JSONMapError: LocalizedError{
var errorDescription: String?{
switch self {
case .emptyKey:
return "key为空"
case .notConformProtocol:
return "没有恪守协议"
}
}
}
var t = WYTeacher()
do{
try t.jsonMap()
}catch{
print(error.localizedDescription)
}
运行结果:
3.3 CustomNSError协议
CustomNSError相当于OC中的NSError,其界说如下,有三个默许特点
界说:
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 }
}
运用:
//CustomNSError相当于NSError
extension JSONMapError: CustomNSError{
var errorCode: Int{
switch self {
case .emptyKey:
return 404
case .notConformProtocol:
return 504
}
}
}
var t = WYTeacher()
do{
try t.jsonMap()
}catch{
print((error as? JSONMapError)?.errorCode)
}
运行结果:
4、总结
- Swift运用Mirror完成反射功用,能够动态获取目标的特点
- 经过Mirror能够完成JSON的解析
- Error是swift中过错类型的根本协议
- 其间LocalizedError、CustomNSError都恪守Error,他们能够供给更详细的信息
- try调用可能发生过错信息的函数