我们⽤下⾯这段代码来测试⼀下:
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 中错误处理的⼏种⽅式:
如何你觉得仅仅使⽤ 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 有三个默认属性: