iOS数据持久化

来源:互联网 发布:2016cba体测数据 编辑:程序博客网 时间:2024/06/06 15:54

今天想来聊聊iOS的数据持久化。因为今天在家辅导表弟,玩iPad的时候,发现XX应用没有对首页做缓存,正好家里网断了(初三小表弟,你懂得),手机共享伤不起。

回归正题,我建议凡是数据比较多的应用,你都要考虑做下缓存,我看今日头条就不错,在网好的时候,它除了新闻的图片不提前缓存,所有首页文字信息都提前缓存下来了,看的很舒服。
iOS数据持久化,无非几种。

分开讲吧,这篇讲,归档吧。(Archiver持久化)

我推荐一个关于Archive的博文,很详细,这里就不多做说明了。点击打开链接

基本的数据类型如NSString、NSDictionary、NSArray、NSData、NSNumber等可以用属性列表的方法持久化到.plist 文件中,但如果是一些自定义的类的话,属性列表的方法就不管用了。archiver 方法可以做到。

这里强调下,NSKeyedArchive 并不是所有对象都可以通过它来归档的,我们想要归档的话,就必须要遵守NSCoding协议

遵守协议是第一步,之后在遵守协议,希望归档的对象实现两个协议方法,就可以实现数据归档了。

一、 encodeWithCoder:(NSCoder *)encoder  代理方法

-(void)encodeWithCoder:(NSCoder *)encoder{  

[super encodeWithCoder:encoder];//不要忘了这个  首先要调用父类的方法,NSObject除外,NSObject 没有实现此方法。

[encoder encodeInt:self.age forKey:@"age"]; 

[encoder encodeObject:self.name forKey:@"name"];  

[encoder encodeFloat:self.height forKey:@"height"];  


二、initWithCoder:(NSCoder *)decoder  代理方法

-(id)initWithCoder:(NSCoder *)decoder{   

self = [super initWithCoder:decoder];//不要忘了这个  

self.age = [decoder decodeIntForKey:@"age"];

self.name = [decoder decodeObjectForKey:@"name"];   

self.height = [decoder decodeFloatForKey:@"height"];

 return self;  

}


之后的操作就是在归档的地方归档在想解档的地方解档

    //创建      -(void)createPerson{                    person *p = [[[person alloc] init] autorelease];          p.age = 20;          p.name = @"Rio";          p.height =1.75f;                    //获得Document的路径          NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];          NSString *path = [documents stringByAppendingPathComponent:@"person.archiver"];//拓展名可以自己随便取                    [NSKeyedArchiver archiveRootObject:p toFile:path];                }            //读取      -(void)readPerson{          NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];          NSString *path = [documents stringByAppendingPathComponent:@"person.archiver"];          person *person1 = [NSKeyedUnarchiver unarchiveObjectWithFile:path];          NSLog(@"%@",person1);      }  

之后,我之前做一款应用时,就用到过这方面来处理缓存

把原理和源码也放在这里了,

原理就是归档,通过请求数据的URL来命名归档的文件名,加上MD5加密一下,基本保证了文件名不重复,

MD5 加密如下,我的处理是给NSString加上了一个类别。


////  ScienceCacheManager.m//  每日新鲜事////  Created by JackYang on 15/9/1.//  Copyright (c) 2015年 JackYang. All rights reserved.//#import "NSString+Hashing.h"#import <CommonCrypto/CommonDigest.h>@implementation NSString (NSString_Hashing)- (NSString *)MD5Hash{    const char *cStr = [self UTF8String];    unsigned char result[16];    CC_MD5(cStr, strlen(cStr), result);    return [NSString stringWithFormat:            @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",            result[0], result[1], result[2], result[3],            result[4], result[5], result[6], result[7],            result[8], result[9], result[10], result[11],            result[12], result[13], result[14], result[15]];}@end



剩下的代码就比较通用了。

我都放在这里了。


////  LimitCachManager.h//  每日新鲜事////  Created by JackYang on 15/9/16.//  Copyright (c) 2015年 JackYang. All rights reserved.//#import <Foundation/Foundation.h>@interface LimitCachManager : NSObject//保存url 对应的数据+ (void)saveData:(id)object atUrl:(NSString*)url;//读取url对应的数据+ (id)readDataAtUrl:(NSString*)ulr;//判断缓存数据是否有效+ (BOOL)isCacheDataInvalid:(NSString*)url;//计算缓存的大小+ (NSInteger)cacheSize;//清除缓存+ (void)clearDisk;@end

主要实现

#import "LimitCachManager.h"#import "NSString+Hashing.h"@implementation LimitCachManager//得到本地缓存的目录+ (NSString*)cacheDirectory{    //得到沙盒目录下的cache文件夹    NSString *cachDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];    cachDir = [cachDir stringByAppendingPathComponent:@"LimitCache"];    //创建LimitCache文件夹,目的是把所有的缓存数据放到该文件夹下面    //attribute:nil只文件夹跟父文件夹一样的读写属性    NSError *error;    BOOL bret = [[NSFileManager defaultManager] createDirectoryAtPath:cachDir withIntermediateDirectories:YES attributes:nil error:&error];    if (!bret) {        NSLog(@"%@",error);        return nil;    }    return cachDir;}+ (NSString*)cacheFileFullPath:(NSString*)url{    //得到保存的文件的全路径,使用url的MD5加密得到的字符串作为文件名    //这样url和文件名就对应起来了    //[url MD5Hash] 是把url进行MD5加密得到的字符串    //MD5 加密算法是不可逆的    NSString *fileName = [url MD5Hash];    NSString *cacheDir = [self cacheDirectory];    return [cacheDir stringByAppendingPathComponent:fileName];}//保存url 对应的数据//输入的数据,要么是字典,要么数组+ (void)saveData:(id)object atUrl:(NSString*)url{    //首先得到保存的文件路径    NSString *fileFullPath = [self cacheFileFullPath:url];    //写入数据,使用NSKeyedArchiver进行数据转换    NSData *data = [NSKeyedArchiver  archivedDataWithRootObject:object];    [data writeToFile:fileFullPath atomically:YES];}//读取url对应的数据+ (id)readDataAtUrl:(NSString*)url{    NSString *fileFullPath = [self cacheFileFullPath:url];    NSData *data = [NSData dataWithContentsOfFile:fileFullPath];    return [NSKeyedUnarchiver unarchiveObjectWithData:data];}//判断缓存数据是否有效+ (BOOL)isCacheDataInvalid:(NSString*)url{    //isDirectory 的参数是返回给我们是否是一个目录    NSString *fileFullPath = [self cacheFileFullPath:url];    BOOL isFileExist = [[NSFileManager defaultManager] fileExistsAtPath:fileFullPath isDirectory:nil];    //获取文件的属性    NSDictionary *attributeDic = [[NSFileManager defaultManager] attributesOfItemAtPath:fileFullPath error:nil];    NSDate *lastModify = attributeDic.fileModificationDate;    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:lastModify];    BOOL isExpire = (timeInterval > 60*60);    if (isFileExist && !isExpire) {        return YES;    }    return NO;}//计算缓存的大小,遍历缓存目录,把文件内容大小累加+ (NSInteger)cacheSize{    NSInteger totalSize = 0;    NSString *cacheDir = [self cacheDirectory];    //得到目录的枚举器,使用它来枚举目录下的所有文件    NSDirectoryEnumerator *enmuerator = [[NSFileManager defaultManager]enumeratorAtPath:cacheDir];    for (NSString *fileName in enmuerator) {        NSString *fileFullPath = [cacheDir stringByAppendingPathComponent:fileName];        NSDictionary *attributeDic = [[NSFileManager defaultManager] attributesOfItemAtPath:fileFullPath error:nil];        totalSize += attributeDic.fileSize;    }    return totalSize;}//清除缓存+ (void)clearDisk{    NSString *cacheDir = [self cacheDirectory];    [[NSFileManager defaultManager] removeItemAtPath:cacheDir error:nil];}@end


当使用是就调用,传入url 存储,读取时先判断文件存在不存在,不存在,就获取,存在就读取本地数据。

然后在清除缓存时,将此缓存一并清除。

0 0
原创粉丝点击