iOS本地数据保存有多种方式,归纳如下:
保存到KeyChain (钥匙串) |
存储为文件 | 存储到数据库 |
---|---|---|
保存到沙盒范围以外的地方,与沙盒无关 | 包括:归档、plist文件存储,偏好设置;归档或者plist文件存储可以选择保存到沙盒中,而偏好设置系统已经规定只能保存到沙盒的 | SQLite,Core Data; |
本章不仅是学习多种数据存储方式,也可学习到其他知识点,下面就让我们详细来看:
储存为文件
- Write写入方式(这里需要注意多种不同的写入方式,作为其中一个知识点,处理不好很多同学容易出错):只能存储常用的类型。
具体方法为:
第一步:获得文件即将保存的路径,并生成在该路径下的文件:
NSString *myDocumentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *zhigangPath = [myDocumentPath stringByAppendingPathComponent:@"zhigang.plist"];
NSArray *array =@[@"study",@"love",@"zhigang"];
第二步:往文件中写入/读取:
方法一:
[array writeToFile:zhigangPath atomically:YES]写入;
NSArray * data = [NSArray arrayWithContentsOfFile:zhigangPath]读取;
方法二:
NSURL *urlPath = [NSURL fileURLWithPath:zhigangPath];
[array writeToURL:urlPath atomically:YES];
NSArray * data = [NSArray arrayWithContentsOfURL:urlPath];
方法三:
NSString*fileURL =[@"file://" stringByAppendingString:zhigangPath];
NSURL*anthorUrlPath = [NSURL URLWithString:fileURL];
[array writeToURL:urlPath atomically:YES];
NSArray * data = [NSArray arrayWithContentsOfURL:anthorUrlPath];
解释下:文中用了fileURLWithPath以及URLWithString两种不同方法,我们要分清楚URL和路径的不同;URL是包含协议头 + 主机地址 +资源路径,如果访问的资源是本机的,那么主机地址可以省略;而路径是不用包含协议头和主机地址的; 用fileURLWithPath方法包含了"file://"协议头,而使用URLWithString创建的URL,与原有的字符串一模一样;故:
当我们需要根据一个字符串创建URL的时候,如果这个字符串包含协议头,那么使用URLWithString,一般用于网络资源的URL创建;如果访问的是本地资源,而且不包含协议头,使用fileURLWithPath创建URL。
2.NSUserDefaults:是一个单例对象,在整个应用程序的生命周期中都只有一个实例。用来保存应用程序设置和属性、用户保存的数据。存储在沙盒的Library/Preference中,NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。写入和读取都比较简单,如下:
写入:
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:@"123" forKey:@"zhigang"];
[userDefault synchronize];
```
读取:
NSString *str = [userDefault objectForKey:@"zhigang"];
3.NSKeyedArchiver:采用归档的形式来保存数据,可归档自定义对象,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码。*(注意对NSInteger,NSString的不同操作;)*
** 单个对象归档:**
@interface Person : NSObject <NSCoding>//遵守NSCoding协议
@property (nonatomic,strong) NSString *name;
@property (nonatomic,assign) NSInteger age;
@end
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeInteger:_age forKey:@"age"];
} - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
_name = [aDecoder decodeObjectForKey:@"name"];
_age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}]
归档操作:
只需要NSCoder子类NSKeyedArchiver的方法archiveRootObject:toFile: 即可
[NSKeyedArchiver archiveRootObject:person toFile:path];]
解档操作:
同样调用NSCoder子类NSKeyedArchiver的方法unarchiveRootObject:toFile: 即可
[NSKeyedUnarchiver unarchiveObjectWithFile:path];
** 多个对象归档:**
对多个对象进行归档,需使用NSData来进行归档对象
NSData可以为一些数据提供临时存储空间,以便随后写入文件,或者存放从磁盘读取的文件内容。可以使用[NSMutableDatadata]创建可变数据空间;
![多对象归档](http://upload-images.jianshu.io/upload_images/2851325-4a39cca7c5875d35.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archiver encodeObject:person forKey:@"person"];
[archiver encodeObject:bir forKey:@"bir"];
// 存档完毕(一定要调用这个方法)
[archiver finishEncoding];
[data writeToFile:path atomically:YES];
NSData *undata = [NSData dataWithContentsOfFile:path];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
[unarchiver decodeObjectForKey:@"person"];
[unarchiver decodeObjectForKey:@"bir"];
// 恢复完毕
[unarchiver finishDecoding];
通过代码基本上发现其实存档和解压是非常简单的一个事情,不过事实这种方式缺点还是很明显的,以这种方式保存数据只能一次性归档保存以及一次性解压。数据较少的时候如果使用感觉比较方便,数据量过多的时候如果想修改其中的某一条,解压整个数据然后归档整个数据还是比较耗时的。
#####存储到数据库