1.用单例设计存储数据接口
1.1单例接口
+ (AppScene *)sharedInstance;
1.2数据序列化接口
- (void)serializeValue:(id)value withKey:(NSString *)key;
1.3数据反序列化接口
- (id)deserializeValueWithKey:(NSString *)key;
2.用单例接口隔离实现细节
2.1替代NSCoding协议
- 在实现之前先简单介绍一下fastCoding,因为过程中会用到fastCoding
fastCoding是用来替代系统的NSCoding的协议 可以将对象序列化成NSData,也可以反序列化成对象。 - fastCodin在github链接或者在github上搜索fastCoding看到star最多的就是。
-
解压得到图中目录,有用的就只有FastCoder目录的两个文件,将这两个文件加入项目中,编译会发现有问题。在ARC下会运行的比较slow,可以手动将这个文件改为MRC环境,操作如图。做完之后,编译没有问题了。
2.2数据接口的实现
- 严格单例的实现(在ios最实用的13中设计模式中的单例模式示例代码中已经详细说明了,没有赏光下载观看的,可以移步git)
+ (AppScene *)sharedInstance {
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
appScene = (AppScene *)AppSceneString;
appScene = [[AppScene alloc] init];
});
//防止子类使用
if (![NSStringFromClass([self class]) isEqualToString:AppSceneString]) {
NSParameterAssert(nil);
}
return appScene;
}
#pragma mark - private
- (instancetype)init {
NSString *string = (NSString *)appScene;
if ([string isKindOfClass:[NSString class]] == YES && [string isEqualToString:AppSceneString]) {
self = [super init];
if (self) {
// 防止子类使用
NSString *classString = NSStringFromClass([self class]);
if (![classString isEqualToString:AppSceneString]) {
NSParameterAssert(nil);
}
}
return self;
} else {
return nil;
}
}
- 数据序列化接口的实现
- (void)serializeValue:(id)value withKey:(NSString *)key {
NSParameterAssert(value);
NSParameterAssert(key);
//fastCoding是用来地点系统的NSCoding的协议
//可以将对象序列化成NSData,也可以反序列化对象
NSData *data = [FastCoder dataWithRootObject:value];
if (data) {
[[NSUserDefaults standardUserDefaults] setObject:data forKey:key];
}
}
- 数据反序列化接口的实现
- (id)deserializeValueWithKey:(NSString *)key {
NSParameterAssert(key);
NSData *data = [[NSUserDefaults standardUserDefaults] valueForKey:key];
return [FastCoder objectWithData:data];
}
3.在单例提供接口的基础上进行上层封装
3.1编写NSObject的category(storeValue),如图所示
3.2category的实现
- (void)serializeValueWithKey:(NSString *)key {
[[AppScene sharedInstance] serializeValue:self withKey:key];
}
+ (id)deserializeValueWithKey:(NSString *)key {
return [[AppScene sharedInstance] deserializeValueWithKey:key];
}
3.3封装的优点
隔离所有细节,假设以后更改实现方法,原有代码无需更改。
4测试
4.1测试结果OK,如图
4.2测试代码,可以感受封装优点
- (void)test1 {
[[AppScene sharedInstance] serializeValue:@{@"A":@"B"} withKey:@"test"];
NSLog(@"------------test1------------");
NSLog(@"%@", [[AppScene sharedInstance] deserializeValueWithKey:@"test"]);
}
- (void)test2 {
Dog *dog = [[Dog alloc] init];
dog.name = @"旺财";
dog.identify = @{@"color" : @"black", @"weight" : @"20kg", @"height" : @"50cm"};
[[AppScene sharedInstance] serializeValue:dog withKey:dog.name];
NSLog(@"-----------test2-------------");
Dog *wangcai = [[AppScene sharedInstance] deserializeValueWithKey:@"旺财"];
NSLog(@"%@", wangcai.identify);
}
//test3在test2的基础上增加了category,在单例提供接口的基础上进行上层封装,隔离所有细节
- (void)test3 {
Dog *dog = [[Dog alloc] init];
dog.name = @"旺旺";
dog.identify = @{@"color" : @"red", @"weight" : @"30kg", @"height" : @"60cm"};
[dog serializeValueWithKey:dog.name];
NSLog(@"-----------test3-------------");
Dog *wangwang = [Dog deserializeValueWithKey:@"旺旺"];
NSLog(@"%@", wangwang.identify);
}
总结
- 单例实现,便于管理,上层封装,代码简洁;
- 实现简单,代码量较小;
- 单独创建的plist,方便其他页面打tag。
(注:最好不要在项目文件的info.plist中加入非必要的信息) - github用单例模式优化本地存储示例代码