iOS NSKeyedArchiver(轻量级缓存)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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(轻量级缓存)的主要内容,如果未能解决你的问题,请参考以下文章

本地缓存方式

iOS开发数据库篇—SQLite简单介绍

iOS开发 - 数据归档与恢复 NSKeyedArchiver

NSKeyedArchiver.unarchiveObject Swift 3 iOS 10

iOS学习 --- iOS12对象序列化(NSKeyedArchiver/NSKeyedUnarchiver)

iOS学习 --- iOS12对象序列化(NSKeyedArchiver/NSKeyedUnarchiver)