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環境,操作如圖。做完之后,編譯沒有問題了。
解壓目錄.png
MRC操作.png
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),如圖所示
category.png
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,如圖
測試結果.png
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用單例模式優化本地存儲示例代碼