请看具体实现,注释详细. 觉得用的上的朋友麻烦点个赞.自己写的实用小工具.
使用的时候直接继承自BaseModel 就可以了
//字典转模型
let model = BaseModel.init(dict: dic)
//一句话快速归档,括号内输入单个模型或者模型数组
model.archiverWithRootObject([model1, model2, model3])
//一句话快速解档.无论你存入的是单个对象还是数组
let modelArray = account.unarchiver()
一句话归档效果,数据是本人的微博信息.
怎么样?是不是非常的cool,以下是两个语言版本的具体实现,希望用的同时能认真看注释,理解其中简单的原理.
OC版本
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@implementation BaseModel
- (instancetype)initWithDic:(NSDictionary *)dic
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dic];
}
return self;
}
#pragma mark 数据持久化
- (void)encodeWithCoder:(NSCoder *)aCoder
{
//获取当前类的所有属性名称
unsigned int outCount, i;
objc_property_t *properties =class_copyPropertyList([self class], &outCount);
//遍历所有的属性名称
for (i = 0; i < outCount; i++)
{
//取出单个属性名称
objc_property_t property = properties[i];
const char* char_f = property_getName(property);
//转换成OC串
NSString *propertyName = [NSString stringWithUTF8String:char_f];
//KVC取值
id propertyValue = [self valueForKey:(NSString *)propertyName];
//如果取出来有值 则归档
if (propertyValue)
{
[aCoder encodeObject:propertyValue forKey:propertyName];
}
}
}
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super init];
if (self)
{
//取出所有的属性名称
unsigned int outCount, i;
objc_property_t *properties =class_copyPropertyList([self class], &outCount);
//遍历属性
for (i = 0; i<outCount; i++)
{
//取出单个属性
objc_property_t property = properties[i];
const char* char_f = property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:char_f];
//KVC赋值
[self setValue:[aCoder decodeObjectForKey:propertyName] forKey:propertyName];
}
}
return self;
}
//存档
+ (void)archiverWithRootObject:(id)rootObject{
NSString *fileName = NSStringFromClass([self class]);
[NSKeyedArchiver archiveRootObject:rootObject toFile:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileName]];
}
//解档
+ (id)unarchiver{
NSString *fileName = NSStringFromClass([self class]);
return [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileName]];
}
@end
Swift版本
//
// BaseModel.swift
// WeiboSwift
//
// Created by 曾凡怡 on 2017/1/5.
// Copyright © 2017年 曾凡怡. All rights reserved.
//
import UIKit
class BaseModel: NSObject,NSCoding {
init(dict : [String : Any]) {
super.init()
setValuesForKeys(dict)
}
required init?(coder aDecoder: NSCoder) {
//先初始化
super.init()
//获取当前类的所有属性名
let nameList = getPropertyNameList()
//进行解档
for key in nameList{
//从aDecoder中取值
let value = aDecoder.decodeObject(forKey: key)
//赋值给自己
setValue(value, forKey: key)
}
}
func encode(with aCoder: NSCoder) {
//获取当前类的所有属性名
let nameList = getPropertyNameList()
//进行归档
for key in nameList{
//KVC取值
if let value = value(forKey: key){
////归档.此处注意归档的方法中要使用带 forKey参数的
aCoder.encode(value, forKey: key)
}
}
}
func getPropertyNameList () -> [String]{
//保存属性的个数
var outCount : UInt32 = 0
//保存属性名称的数组
var list : [String] = []
//获取属性集合
let property = class_copyPropertyList(type(of:self), &outCount)
//解包
guard let propertyList = property else {
return list
}
for i in 0 ..< Int(outCount){
//取出单个属性
let property = propertyList[i]
//获取属性的名字
guard let char_f = property_getName(property) else{
continue
}
//转换为String
if let key = NSString(cString: char_f, encoding: String.Encoding.utf8.rawValue) as? String {
//添加到数组
list.append(key)
}
}
return list
}
func archiverWithRootObject(_ rootObjcet : Any){
let filePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last!
let fileName = NSStringFromClass(self.classForCoder) as String
let savePath = filePath + "/" + fileName + ".plist"
//归档
NSKeyedArchiver.archiveRootObject(rootObjcet, toFile:savePath)
}
func unarchiver()->Any?{
let filePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last!
let fileName = NSStringFromClass(self.classForCoder) as String
let savePath = filePath + "/" + fileName + ".plist"
//解档出来的元素
return NSKeyedUnarchiver.unarchiveObject(withFile: savePath)
}
}
巨坑
Swift的巨坑!!!...哭了一下午,一直在解档崩溃.最后发现问题在归档.
//下面两种归档的方法要注意了.不要使用第一种归档.
~~aCoder.encode(object: Any?)~~ 警告,不要使用
//而第二种方法因为第一个参数没有外部参数,很难打出来.
aCoder.encode(objv: Any?, forKey: String)
//输入aCoder.encodeforkey 来查找这个方法
网友评论