首页 > 代码库 > iOS NSKeyedArchiver(轻量级缓存)
iOS NSKeyedArchiver(轻量级缓存)
iOS本地缓存数据方式有五种:
1.直接写文件方式:可以存储的对象有NSString、NSArray、NSDictionary、NSData、NSNumber,数据全部存放在一个属性列表文件(*.plist文件)中。
2.NSUserDefaults(偏好设置),用来存储应用设置信息,文件放在perference目录下。
3.归档操作(NSkeyedArchiver),不同于前面两种,它可以把自定义对象存放在文件中。
4.coreData:coreData是苹果官方iOS5之后推出的综合型数据库,其使用了ORM(Object Relational Mapping)对象关系映射技术,将对象转换成数据,存储在本地数据库中。coreData为了提高效率,甚至将数据存储在不同的数据库中,且在使用的时候将本地数据放到内存中使得访问速度更快。我们可以选择coreData的数据存储方式,包括sqlite、xml等格式。但也正是coreData 是完全面向对象的,其在执行效率上比不上原生的数据库。除此之外,coreData拥有数据验证、undo等其他功能,在功能上是几种持久化方案最多的。
5.FMDB:FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API,使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码,对比苹果自带的Core Data框架,更加轻量级和灵活,提供了多线程安全的数据库操作方法,有效地防止数据混乱。
接下来我将介绍第三种缓存机制 归档操作:
作为轻量级存储的持久化方案,数据归档是进行加密处理的,数据在经过归档处理会转换成二进制数据,所以安全性要远远高于属性列表。另外使用归档方式,我们可以将复杂的对象写入文件中,并且不管添加多少对象,将对象写入磁盘的方式都是一样的。
使用NSKeyedArchiver对自定义的数据进行序列化,并且保存在沙盒目录下。使用这种归档的前提是让存储的数据模型遵守NSCoding协议并且实现其两个协议方法。(当然,如果为了更加安全的存储,也可以遵守NSSecureCoding协议,这是iOS6之后新增的特性)
使用归档操作存储数据的主要好处是,不同于前面两种方法只能存储几个常用的数据类型的数据,NSKeyedArchiver可以存储自定义的对象。
/**代码示例**/
先创建一个继承NSObject的类,该类遵守NSCoding协议
#import <Foundation/Foundation.h>
@interface JXItem : NSObject<NSCoding>
@property (nonatomic, assign) NSInteger collect;
@property (nonatomic, assign) NSInteger collect_num;
@property (nonatomic, assign) NSInteger courseid;
@property (nonatomic, copy) NSString *coverpic;
@property (nonatomic, assign) long long date_end;
@property (nonatomic, assign) long long date_start;
@property (nonatomic, assign) NSInteger groupid;
@property (nonatomic, assign) NSInteger invitation_code;
@property (nonatomic, assign) NSInteger is_live;
@property (nonatomic, assign) NSInteger paid;
@property (nonatomic, assign) NSInteger play_num;
@property (nonatomic, copy) NSString *price;
@property (nonatomic, assign) NSInteger product_id;
@property (nonatomic, copy ) NSString *product_info;
@property (nonatomic, copy) NSString *productname;
@property (nonatomic, copy) NSString *realname;
@property (nonatomic,assign) NSInteger recomment;
@property (nonatomic ,copy) NSString *stream_url;
@property (nonatomic, copy) NSString *time_duan;
@property (nonatomic,assign) NSInteger user_id;
@property (nonatomic, assign) NSInteger viewtype;
@property (nonatomic, assign) NSInteger live_in;
+ (instancetype)randomDictionary:(NSDictionary *)dictionary;
@end
其次在模型的.m文件进行读取解析,归档和解归档
#import "JXItem.h"
@implementation JXItem
+ (instancetype)randomDictionary:(NSDictionary *)dictionary {
JXItem *item = [[JXItem alloc] init];
[item setValuesForKeysWithDictionary:dictionary];
return item;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInteger:self.collect forKey:@"collect"];
[aCoder encodeInteger:self.collect_num forKey:@"collect_num"];
[aCoder encodeInteger:self.courseid forKey:@"courseid"];
[aCoder encodeObject:self.coverpic forKey:@"coverpic"];
[aCoder encodeInteger:self.date_end forKey:@"date_end"];
[aCoder encodeInteger:self.date_start forKey:@"date_start"];
[aCoder encodeInteger:self.groupid forKey:@"groupid"];
[aCoder encodeInteger:self.invitation_code forKey:@"invitation_code"];
[aCoder encodeInteger:self.paid forKey:@"paid"];
[aCoder encodeInteger:self.play_num forKey:@"play_num"];
[aCoder encodeObject:self.price forKey:@"price"];
[aCoder encodeInteger:self.product_id forKey:@"product_id"];
[aCoder encodeObject:self.product_info forKey:@"product_info"];
[aCoder encodeObject:self.productname forKey:@"productname"];
[aCoder encodeObject:self.realname forKey:@"realname"];
[aCoder encodeInteger:self.recomment forKey:@"recomment"];
[aCoder encodeObject:self.stream_url forKey:@"stream_url"];
[aCoder encodeObject:self.time_duan forKey:@"time_duan"];
[aCoder encodeInteger:self.user_id forKey:@"user_id"];
[aCoder encodeInteger:self.viewtype forKey:@"viewtype"];
[aCoder encodeInteger:self.live_in forKey:@"live_in"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
_collect = [aDecoder decodeIntegerForKey:@"collect"];
_collect_num = [aDecoder decodeIntegerForKey:@"collect_num"];
_coverpic = [aDecoder decodeObjectForKey:@"coverpic"];
_date_end = [aDecoder decodeIntegerForKey:@"date_end"];
_date_start = [aDecoder decodeIntegerForKey:@"date_start"];
_groupid = [aDecoder decodeIntegerForKey:@"groupid"];
_invitation_code = [aDecoder decodeIntegerForKey:@"invitation_code"];
_paid = [aDecoder decodeIntegerForKey:@"paid"];
_price = [aDecoder decodeObjectForKey:@"price"];
_product_id = [aDecoder decodeIntegerForKey:@"product_id"];
_product_info = [aDecoder decodeObjectForKey:@"product_info"];
_productname = [aDecoder decodeObjectForKey:@"productname"];
_realname = [aDecoder decodeObjectForKey:@"realname"];
_recomment = [aDecoder decodeIntegerForKey:@"recomment"];
_stream_url = [aDecoder decodeObjectForKey:@"stream_url"];
_time_duan = [aDecoder decodeObjectForKey:@"time_duan"];
_viewtype = [aDecoder decodeIntegerForKey:@"viewtype"];
}
return self;
}
@end
另外建立一个数据的管理类JXItemStore
#import <Foundation/Foundation.h>
@class JXItem;
@interface JXItemStore : NSObject
@property (nonatomic, copy) NSString *archiveName;
@property (nonatomic, strong) NSArray *allItem;
+ (instancetype)sharedStore;
- (JXItem *)createItem:(JXItem *)item;
/**
* 删除对象
*
* @param item 需要删除的对象
*/
- (void)removeItem:(JXItem *)item;
/**
* 移除对象
*
* @param fromIndex 移除对象的起始位置
* @param toIndex 移除后的位置
*/
- (void)moveItemAtIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex;
- (BOOL)saveChanages;
@end
//
#import "JXItemStore.h"
#import "JXItem.h"
@interface JXItemStore()
@property (nonatomic, strong) NSMutableArray *privateItems;
@end
@implementation JXItemStore
+ (instancetype)sharedStore {
static JXItemStore *sharedStore = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedStore = [[self alloc] init];
});
return sharedStore;
}
- (BOOL)saveChanages {
return [NSKeyedArchiver archiveRootObject:self.privateItems
toFile:[self itemArchivePath]];
}
- (NSArray *)getAll {
[self.privateItems setArray:[NSKeyedUnarchiver unarchiveObjectWithFile: [self itemArchivePath]]];
return self.privateItems;
}
- (void)removeItem:(JXItem *)item {
[self.privateItems removeObjectIdenticalTo:item];
//
}
- (void)moveItemAtIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex {
if (fromIndex == toIndex) {
return;
}
JXItem *item = self.privateItems[fromIndex];
[self.privateItems removeObjectAtIndex:fromIndex];
[self.privateItems insertObject:item atIndex:toIndex];
}
- (NSMutableArray *)privateItems {
if (!_privateItems) {
_privateItems = [[NSMutableArray alloc] init];
[self getAll];
}
return _privateItems;
}
- (NSArray *)allItem {
return [self.privateItems copy];
}
- (JXItem *)createItem:(JXItem *)item {
[self.privateItems addObject:item];
return item;
}
- (NSString *)itemArchivePath {
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories firstObject];
if (!_archiveName) {
return [documentDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"putcharTems.archive"]];
}
return [documentDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@items.archive",_archiveName]];
}
这样子,我们就可以进行数据的请求了 ZXHttpRequestManager类只是一个对AFNetworking请求库封装的一个网络请求管理类
#define kDomain_name @"www.niulaile.tv"//test.91kanjian.com"
#import "ViewController.h"
#import "ZXHttpRequestManager.h"
#import "JXItemStore.h"
#import "JXItem.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *url = [NSString stringWithFormat:@"http://%@//kj.php?m=Course&a=dotv_newindex",kDomain_name];
JXItemStore *manager = [JXItemStore sharedStore];
manager.archiveName = @"JXModel";
__weak typeof(manager) weakManager = manager;
[[ZXHttpRequestManager manager] POST:url parameters:nil success:^(ZXHttpRequestCode code, id response) {
if(code == ZXHttpRequestSuccess) {
if([response[@"status"] integerValue] == 1) {
for (NSDictionary *dict in response[@"data"]) {
JXItem *item = [JXItem randomDictionary:dict];
[weakManager createItem:item];
}
NSArray *array = weakManager.allItem;
NSLog(@"%@",array);
}
}
} failure:^(NSInteger errorCode, NSError *error) {
NSArray *array = weakManager.allItem;
NSLog(@"%@",array);
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
iOS NSKeyedArchiver(轻量级缓存)