前言
众所周知,很多编程语言都有toString()
方法,旨在很简单地输出对象信息,当然Swift也有类似的方法 - description
属性。如果想个性的打印对象信息,就需要重写description属性。
需求
打印任一对象的属性信息(实际工作中,一般是在开发阶段中打印 model 信息,这里就按这种需求举例)
阅读前的准备
假设已经熟悉 Swift 反射相关知识(可以参考我的另一篇文章:Swift-Reflection)
主要代码
class BaseModel: NSObject {
override var description: String {
// 获取属性列表
let clazz: NSObject.Type = type(of: self)
// 通过反射获取对象的所有属性
if let propertyList: [[String : Any]] = SwiftReflectionTool.propertyList(clazz: clazz) {
var result = "[\(type(of: self))] ==> "
for dict in propertyList {
let (key, _) = SwiftReflectionTool.convert(dict: dict)
let value = self.value(forKeyPath: key) ?? ""
let subStr = "\(key)=\(value); "
// 拼接字符串
result += subStr
}
return result
}
return ""
}
}
// 控制台打印结果如下:
[Book] ==> title=XXX从入门到放弃; author=cy; numberOfPages=250; released=2017-07-10 07:00:06 +0000; isSaled=1;
代码分析
- 可以打印继承自BaseModel的对象信息
- 每次打印的时候都会获取所有属性!
代码优化
优化方案
使用缓存(这里使用的是
PINCache
内存缓存方案)!
主要代码
BaseKitModel.swift
class BaseKitModel: NSObject {
override init() {
super.init()
// 设置唯一标识
BaseKitModelService.id = "\(type(of: self))"
}
override var description: String {
// 获取属性列表
let propertyList: [[String : Any]]?
if let cacheList = BaseKitModelService.propertyList, cacheList.count > 0 {
// 从缓存中取
propertyList = cacheList
} else {
// 动态获取
propertyList = SwiftReflectionTool.propertyList(obj: self)
BaseKitModelService.propertyList = propertyList
}
if let propertyList = propertyList {
var result = "[\(BaseKitModelService.id ?? "")] ==> "
for dict in propertyList {
let (key, _) = SwiftReflectionTool.convert(dict: dict)
let value = self.value(forKeyPath: key) ?? ""
let subStr = "\(key)=\(value); "
result += subStr
}
return result
}
return ""
}
deinit {
print("Deinit: \(NSStringFromClass(type(of: self)))")
// 对象释放时,清除缓存
BaseKitModelService.cache.removeAllObjects()
}
}
BaseKitModelService.swift
open class BaseKitModelService {
static let sharedInstance = BaseKitModelService()
private init() {}
static let cache = PINMemoryCache.shared()
static var id: String? {
didSet {
KEY = "BaseKitModelServiceKey4\(id ?? "")"
}
}
private static var KEY = "BaseKitModelServiceKey4"
static var propertyList: [[String : Any]]? {
get {
let key: String? = KEY // 多此一举! 目的:为了不默认调用另一个无返回值的重载方法!
if let list = cache.object(forKey: key) as? [[String: Any]] {
return list
}
return nil
}
set {
if let value = newValue {
cache.setObject(value as NSCoding, forKey: KEY)
} else {
cache.removeObject(forKey: KEY)
}
}
}
}
网友评论