因为 swift NSCoding 方法是 required 修饰,所以无法通过 Objc 分类实现默认的编解码;只能在对应的方法中调用通用方法。用于储存详情 model,特别方便
@objc public extension NSObject{
/// 类的字符串名称
static let identifier = String(describing: self)
///遍历成员变量列表
func enumerateIvars(_ block: @escaping ((Ivar, String, Any?)->Void)) {
var count: UInt32 = 0
guard let list = class_copyIvarList(self.classForCoder, &count) else { return }
defer {
free(list)// 释放c语言对象
}
for i in 0..<Int(count) {
let ivar = list[i]
//转换成String字符串
guard let name = ivar_getName(ivar),
let strName = String(cString: name, encoding: String.Encoding.utf8) else {
//继续下一次遍历
continue
}
//利用kvc 取值
let value = self.value(forKey: strName)
block(ivar, strName, value)
}
}
///遍历属性列表
func enumeratePropertys(_ block: @escaping ((objc_property_t, String, Any?)->Void)) {
var count: UInt32 = 0
guard let list = class_copyPropertyList(self.classForCoder, &count) else { return }
defer {
free(list)// 释放c语言对象
}
for i in 0..<Int(count) {
let property: objc_property_t = list[i]
//获取成员变量的名称 -> c语言字符串
let name = property_getName(property)
//转换成String字符串
guard let strName = String(cString: name, encoding: String.Encoding.utf8) else {
//继续下一次遍历
continue
}
//利用kvc 取值
let value = self.value(forKey: strName)
block(property, strName, value)
}
}
///遍历方法列表
func enumerateMethods(_ block: @escaping ((Method, String)->Void)) {
var count: UInt32 = 0
guard let list = class_copyMethodList(self.classForCoder, &count) else { return }
defer {
free(list)// 释放c语言对象
}
for i in 0..<Int(count) {
let method: Method = list[i]
//获取成员变量的名称 -> c语言字符串
let name: Selector = method_getName(method)
//转换成String字符串
let strName = NSStringFromSelector(name)
block(method, strName)
}
}
///遍历遵循的协议列表
func enumerateProtocols(_ block: @escaping ((Protocol, String)->Void)) {
var count: UInt32 = 0
guard let list = class_copyProtocolList(self.classForCoder, &count) else { return }
for i in 0..<Int(count) {
let proto: Protocol = list[i]
//获取成员变量的名称 -> c语言字符串
let name = protocol_getName(proto)
//转换成String字符串
guard let strName = String(cString: name, encoding: String.Encoding.utf8) else {
//继续下一次遍历
continue
}
block(proto, strName)
}
}
/// 模型自动编码
func se_encode(with aCoder: NSCoder) {
enumeratePropertys { (property, name, value) in
guard let value = self.value(forKey: name) else { return }
//进行编码
aCoder.encode(value, forKey: name)
}
}
/// 模型自动解码
func se_decode(with aDecoder: NSCoder) {
enumeratePropertys { (property, name, value) in
//进行解档取值
guard let value = aDecoder.decodeObject(forKey: name) else { return }
//利用kvc给属性赋值
self.setValue(value, forKeyPath: name)
}
}
/// 字典转模型
convenience init(dic: [String: Any]) {
self.init();
self.setValuesForKeys(dic)
}
///详情模型转字典(不支持嵌套)
func toDictionary() -> [AnyHashable : Any] {
var dic: [AnyHashable : Any] = [:]
self.enumeratePropertys { (property, name, value) in
dic[name] = value ?? ""
}
return dic
}
}
🌰🌰:
@objcMembers
class CCSParkItemModel: NSObject, HandyJSON, NSCoding {
var arm_version: String = ""
var channel_list: [CCSParkChannelModel]?
var park_code: String = ""
var parking_name: String = ""
required override init() {}
func mapping(mapper: HelpingMapper) {
}
// MARK: -NSCoding
required init?(coder aDecoder: NSCoder) {
super.init()
se_decode(with: aDecoder)
}
func encode(with aCoder: NSCoder) {
se_encode(with: aCoder)
}
// required init?(coder aDecoder: NSCoder) {
// arm_version = aDecoder.decodeObject(forKey: "arm_version") as! String
// channel_list = aDecoder.decodeObject(forKey: "channel_list") as? [CCSParkChannelModel]
// park_code = aDecoder.decodeObject(forKey: "park_code") as! String
// parking_name = aDecoder.decodeObject(forKey: "parking_name") as! String
// }
//
// func encode(with aCoder: NSCoder) {
// aCoder.encode(arm_version, forKey: "arm_version")
// aCoder.encode(channel_list, forKey: "channel_list")
// aCoder.encode(park_code, forKey: "park_code")
// aCoder.encode(parking_name, forKey: "parking_name")
// }
}
网友评论