基础太差...
一点一点来...
现在还不晚...
NSSecureCoding继承NSCoding...
数据归档过程多了数据类型检验...
相对更安全一点...
使用NSSecureCoding...
需要实现...
+(BOOL)supportsSecureCoding
/** 编码*/
-(instancetype)initWithCoder:(NSCoder *)aDecoder
/** 解码*/
-(void)encodeWithCoder:(NSCoder *)aCoder
多secure coding笔coding多一个传一个类型判断...
基本类型可以转成NSValue,或者NSNumber...
在编码initWithCoder中,设置每一个属性的编码...
self.dataList = [aDecoder decodeObjectOfClass:[NSMutableArray class] forKey:@"dataList"];
self.secureTitle = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"secureTitle"];
self.secureIndex = [[aDecoder decodeObjectOfClass:[NSNumber class] forKey:@"secureIndex"] integerValue];
self.superObj = [aDecoder decodeObjectOfClass:[SecureObj class] forKey:@"superObj"];
self.secureContent = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"secureContent"];
在编码encodeWithCoder中,解码获取相应的值...
[aCoder encodeObject:self.dataList forKey:@"dataList"];
[aCoder encodeObject:self.secureTitle forKey:@"secureTitle"];
[aCoder encodeObject:self.superObj forKey:@"superObj"];
[aCoder encodeObject:@(self.secureIndex) forKey:@"secureIndex"];
[aCoder encodeObject:self.secureContent forKey:@"secureContent"];
基本设置好了之后...
开始使用...
/** 归档成data 直接传到服务端、或者本地存储*/
+ (NSData *)archivedDataWithRootObject:(id)rootObject;
/** 直接存本地路劲path*/
+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;
假设将存在本地沙盒...
路劲...
- (NSString *)pathArchive
{
NSString * path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
path = [path stringByAppendingPathComponent:@"archive"];
NSLog(@"###### %@",path);
return path;
}
通过NSKeyedArchiver 开始 archive...
SecureObj * obj = [SecureObj new];
obj.secureTitle = self.titleField.text;
obj.secureContent = self.contentTextView.text;
[NSKeyedArchiver archiveRootObject:obj toFile:[self pathArchive]];
通过NSKeyedUnarchiver 开始 unarchive...
SecureObj * obj = [NSKeyedUnarchiver unarchiveObjectWithFile:[self pathArchive]];
self.titleField.text = obj.secureTitle;
self.contentTextView.text = obj.secureContent;
但是有一个问题...
我们如果加一个属性...
都要去设置一遍decode,encode...
如果需要更懒,一步设置...
知道所有属性的名字...
对应属性的数据类型...
通过runtime可以对属性进行很多操作...
用到哪学到哪...
通过runtime获取类中属性的列表....
///通过运行时获取当前对象的所有属性的名称,以数组的形式返回
- (NSArray *) allPropertyNames{
///存储所有的属性名称
NSMutableArray *allNames = [[NSMutableArray alloc] init];
///存储属性的个数
unsigned int propertyCount = 0;
///通过运行时获取当前类的属性
objc_property_t *propertys = class_copyPropertyList([self class], &propertyCount);
//把属性放到数组中
for (int i = 0; i < propertyCount; i ++) {
///取出第一个属性
objc_property_t property = propertys[i];
const char * propertyName = property_getName(property);
[allNames addObject:[NSString stringWithUTF8String:propertyName]];
}
///释放
free(propertys);
return allNames;
}
获取属性的数据类型信息...
NSMutableDictionary * dictionary = objc_getAssociatedObject([self class], _cmd);
if(dictionary)
{
return dictionary;
}
dictionary = [NSMutableDictionary dictionary];
Class subClass = [self class];
while (subClass != [NSObject class] && subClass)
{
unsigned int propertyCount;
objc_property_t * properties = class_copyPropertyList([self class], &propertyCount);
for(int i = 0; i < propertyCount; i++)
{
objc_property_t property = properties[i];
const char * propertyName = property_getName(property);
NSString * key = @(propertyName);
char * ivar = property_copyAttributeValue(property, "V");
if(ivar)
{
NSString *ivarName = @(ivar);
if ([ivarName isEqualToString:key] ||
[ivarName isEqualToString:[@"_" stringByAppendingString:key]])
{
Class propertyClass = nil;
char *typeEncoding = property_copyAttributeValue(property, "T");
switch (typeEncoding[0])
{
case 'c': // Numeric types
case 'i':
case 's':
case 'l':
case 'q':
case 'C':
case 'I':
case 'S':
case 'L':
case 'Q':
case 'f':
case 'd':
case 'B':
{
propertyClass = [NSNumber class];
break;
}
case '*': // C-String
{
propertyClass = [NSString class];
break;
}
case '@': // Object
{
NSString * classStr = @(typeEncoding);
classStr = [classStr stringByReplacingOccurrencesOfString:@"@" withString:@""];
classStr = [classStr stringByReplacingOccurrencesOfString:@"\"" withString:@""];
classStr = [classStr stringByReplacingOccurrencesOfString:@"\\" withString:@""];
propertyClass = NSClassFromString(classStr);
break;
}
case '{': // Struct
{
propertyClass = [NSValue class];
break;
}
case '[': // C-Array
case '(': // Enum
case '#': // Class
case ':': // Selector
case '^': // Pointer
case 'b': // Bitfield
case '?': // Unknown type
default:
{
propertyClass = nil; // Not supported by KVC
break;
}
}
free(typeEncoding);
// If known type, add to dictionary
if (propertyClass)
{
dictionary[key] = propertyClass;
}
}
}
free(ivar);
subClass = [subClass superclass];
}
objc_setAssociatedObject([self class], _cmd, dictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return dictionary;
在decode时候...
[[self getPropertyClassesByName] enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull propertyClass, BOOL * _Nonnull stop) {
id object = [aDecoder decodeObjectOfClass:propertyClass forKey:key];
if (object)
{
[self setValue:object forKey:key];
}
}];
encode...
for (NSString *key in [self getPropertyClassesByName])
{
id object = [self valueForKey:key];
if (object)
{
[aCoder encodeObject:object forKey:key];
}
}
以上仅代表个人观点...
有错误欢迎指出...
源码地址...
参考资料:
数据持久化(归档反归档)
runtime
----