//归档
- (IBAction)archiverHandle:(id)sender {
//创建学生对象
Student *stu = [[Student alloc] init];
stu.name = self.nameTF.text;
stu.age = self.ageTF.text;
//归档
//1.归档对象
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//2.归档 归档的对象必须服从NSCoding协议 实现encideWithCoder:
[archiver encodeObject:stu forKey:@"JingJing"];
//3.归档完成
[archiver finishEncoding];
//数据持久化
//获取文件路径
NSString *temPath = NSTemporaryDirectory();
//拼接
NSString *filePath = [temPath stringByAppendingString:@"/student.plist"];
//写入
[data writeToFile:filePath atomically:YES];
}
//反归档
- (IBAction)unarchiverHandle:(id)sender {
//获取文件路径
NSString *temPath = NSTemporaryDirectory();
//拼接
NSString *filePath = [temPath stringByAppendingString:@"/student.plist"];
//通过文件路径获取数据
NSData *data = [NSData dataWithContentsOfFile:filePath];
//反归档
//1.创建反归档对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
//2.反归档操作
Student *stu = [unarchiver decodeObjectForKey:@"JingJing"];
//3.反归档完成
[unarchiver finishDecoding];
self.nameTF.text = stu.name;
self.ageTF.text = stu.age;
NSLog(@"%@",stu);
}
归档和反归档的数据需要服从 <NSCoding>协议,同时需要实现以下方法
//归档需要实现的方法
-(void)encodeWithCoder:(NSCoder *)aCoder
{
//对每一个属性进行归档操作
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.age forKey:@"age"];
}
//反归档需要实现的方法
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
//对每一个属性进行反归档操作
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeObjectForKey:@"age"];
}
return self;
}
#import "NSObject+NSCoding.h"
model类中服从NSCoding协议后需要实现的方法
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[self autoEncodeWithCoder:aCoder];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
[self autoDecode:aDecoder];
}
return self;
}
eg:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface NSObject (NSCoding)
- (void)autoEncodeWithCoder: (NSCoder *)coder;
- (void)autoDecode:(NSCoder *)coder;
- (NSDictionary *)properties;
@end
#import "NSObject+NSCoding.h"
#import <objc/runtime.h>
@implementation NSObject (NSCoding)
- (NSMutableDictionary *)propertiesForClass:(Class)klass {
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(klass, &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSString *pname = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
NSString *pattrs = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
pattrs = [[pattrs componentsSeparatedByString:@","] objectAtIndex:0];
pattrs = [pattrs substringFromIndex:1];
[results setObject:pattrs forKey:pname];
}
free(properties);
if ([klass superclass] != [NSObject class]) {
[results addEntriesFromDictionary:[self propertiesForClass:[klass superclass]]];
}
return results;
}
- (NSDictionary *)properties {
return [self propertiesForClass:[self class]];
}
- (void)autoEncodeWithCoder:(NSCoder *)coder {
NSDictionary *properties = [self properties];
for (NSString *key in properties) {
NSString *type = [properties objectForKey:key];
id value;
unsigned long long ullValue;
BOOL boolValue;
float floatValue;
double doubleValue;
NSInteger intValue;
unsigned long ulValue;
long longValue;
unsigned unsignedValue;
short shortValue;
NSString *className;
NSMethodSignature *signature = [self methodSignatureForSelector:NSSelectorFromString(key)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:NSSelectorFromString(key)];
[invocation setTarget:self];
switch ([type characterAtIndex:0]) {
case '@': // object
if ([[type componentsSeparatedByString:@"\""] count] > 1) {
className = [[type componentsSeparatedByString:@"\""] objectAtIndex:1];
Class class = NSClassFromString(className);
#warning UIImage类型的属性不归档 add by yhy
if ([className isEqualToString:@"UIImage"]) {
//如果属性是UIImage类型的,不进行归档
break;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
value = [self performSelector:NSSelectorFromString(key)];
#pragma clang diagnostic pop
// only decode if the property conforms to NSCoding
if([class conformsToProtocol:@protocol(NSCoding)]){
[coder encodeObject:value forKey:key];
}
}
break;
case 'c': // bool
[invocation invoke];
[invocation getReturnValue:&boolValue];
[coder encodeObject:[NSNumber numberWithBool:boolValue] forKey:key];
break;
case 'f': // float
[invocation invoke];
[invocation getReturnValue:&floatValue];
[coder encodeObject:[NSNumber numberWithFloat:floatValue] forKey:key];
break;
case 'd': // double
[invocation invoke];
[invocation getReturnValue:&doubleValue];
[coder encodeObject:[NSNumber numberWithDouble:doubleValue] forKey:key];
break;
case 'i': // int
[invocation invoke];
[invocation getReturnValue:&intValue];
[coder encodeObject:[NSNumber numberWithInt:intValue] forKey:key];
break;
case 'L': // unsigned long
[invocation invoke];
[invocation getReturnValue:&ulValue];
[coder encodeObject:[NSNumber numberWithUnsignedLong:ulValue] forKey:key];
break;
case 'Q': // unsigned long long
[invocation invoke];
[invocation getReturnValue:&ullValue];
[coder encodeObject:[NSNumber numberWithUnsignedLongLong:ullValue] forKey:key];
break;
case 'l': // long
[invocation invoke];
[invocation getReturnValue:&longValue];
[coder encodeObject:[NSNumber numberWithLong:longValue] forKey:key];
break;
case 's': // short
[invocation invoke];
[invocation getReturnValue:&shortValue];
[coder encodeObject:[NSNumber numberWithShort:shortValue] forKey:key];
break;
case 'I': // unsigned
[invocation invoke];
[invocation getReturnValue:&unsignedValue];
[coder encodeObject:[NSNumber numberWithUnsignedInt:unsignedValue] forKey:key];
break;
default:
break;
}
}
}
- (void)autoDecode:(NSCoder *)coder {
NSDictionary *properties = [self properties];
for (NSString *key in properties) {
NSString *type = [properties objectForKey:key];
id value;
NSNumber *number;
NSInteger i;
CGFloat f;
BOOL b;
double d;
unsigned long ul;
unsigned long long ull;
long longValue;
unsigned unsignedValue;
short shortValue;
NSString *className;
switch ([type characterAtIndex:0]) {
case '@': // object
if ([[type componentsSeparatedByString:@"\""] count] > 1) {
className = [[type componentsSeparatedByString:@"\""] objectAtIndex:1];
Class class = NSClassFromString(className);
#warning UIImage类型的属性不归档 add by yhy
if ([className isEqualToString:@"UIImage"]) {
//如果属性是UIImage类型的,不进行反归档
break;
}
// only decode if the property conforms to NSCoding
if ([class conformsToProtocol:@protocol(NSCoding )]){
value = [coder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
}
break;
case 'c': // bool
number = [coder decodeObjectForKey:key];
b = [number boolValue];
[self setValue:@(b) forKey:key];
break;
case 'f': // float
number = [coder decodeObjectForKey:key];
f = [number floatValue];
[self setValue:@(f) forKey:key];
break;
case 'd': // double
number = [coder decodeObjectForKey:key];
d = [number doubleValue];
[self setValue:@(d) forKey:key];
break;
case 'i': // int
number = [coder decodeObjectForKey:key];
i = [number intValue];
[self setValue:@(i) forKey:key];
break;
case 'L': // unsigned long
number = [coder decodeObjectForKey:key];
ul = [number unsignedLongValue];
[self setValue:@(ul) forKey:key];
break;
case 'Q': // unsigned long long
number = [coder decodeObjectForKey:key];
ull = [number unsignedLongLongValue];
[self setValue:@(ull) forKey:key];
break;
case 'l': // long
number = [coder decodeObjectForKey:key];
longValue = [number longValue];
[self setValue:@(longValue) forKey:key];
break;
case 'I': // unsigned
number = [coder decodeObjectForKey:key];
unsignedValue = [number unsignedIntValue];
[self setValue:@(unsignedValue) forKey:key];
break;
case 's': // short
number = [coder decodeObjectForKey:key];
shortValue = [number shortValue];
[self setValue:@(shortValue) forKey:key];
break;
default:
break;
}
}
}
@end