[ios] 数据持久化(加密等)
从数据保存的方式上讲可以分为三大部分:属性列表、对象归档、嵌入式数据库(SQLite3)、CoreData等
这里主要解释 属性列表,对象归档
1.属性列表
首先要知道获取应用程序中能保存数据的路径, http://www.cnblogs.com/jinjiantong/archive/2013/02/23/2923717.html 这里提过
1)一种简单的方法是,获取目录路径后直接写下去
-(IBAction) save {
NSArray * myPaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString * myDocPath = [myPaths objectAtIndex:0];
NSString *filename = [myDocPath
stringByAppendingPathComponent:@"properties.plist"];
NSMutableArray *data = [[NSMutableArray alloc]init];
[data addObject:studentId.text];
[data addObject:studentName.text];
[data addObject:studentClass.text];
[data writeToFile:filename atomically:YES];
[data release];
}
读取
NSArray * myPaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString * myDocPath = [myPaths objectAtIndex:0];
NSString *filename = [myDocPath
stringByAppendingPathComponent:@"properties.plist"];
if ([[NSFileManager defaultManager] fileExistsAtPath:filename]) {
NSArray *data = [[NSArray alloc] initWithContentsOfFile:filename];
studentId.text = [data objectAtIndex:0];
studentName.text = [data objectAtIndex:1];
studentClass.text = [data objectAtIndex:2];
[data release];
}
}
2)用NSUserdefault
用NSUserdefault存储的数据在ios应用程序目录中/Library/Prefereces,里面有个plist文件,存储的就是你的userDefaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"mytest" forKey:@"mytest"];
[defaults synchronize]; //同步化,更新你的数据 (我理解为把内存中的数据写入到文件)
NSString *testStr = [defaults objectForKey:@"myTest"];
NSLog(@"testStr is: %@",testStr);
3)keychain 的使用(加密)
来至:http://blog.csdn.net/weiqubo/article/details/7691278
需要导入Security.framework
- @implementation WQKeyChain
- + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
- return [NSMutableDictionary dictionaryWithObjectsAndKeys:
- (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
- service, (__bridge_transfer id)kSecAttrService,
- service, (__bridge_transfer id)kSecAttrAccount,
- (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,
- nil];
- }
- + (void)save:(NSString *)service data:(id)data {
- //Get search dictionary
- NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
- //Delete old item before add new item
- SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
- //Add new object to search dictionary(Attention:the data format)
- [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge_transfer id)kSecValueData];
- //Add item to keychain with the search dictionary
- SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL);
- }
- + (id)load:(NSString *)service {
- id ret = nil;
- NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
- //Configure the search setting
- [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];
- [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit];
- CFDataRef keyData = NULL;
- if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
- @try {
- ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];
- } @catch (NSException *e) {
- NSLog(@"Unarchive of %@ failed: %@", service, e);
- } @finally {
- }
- }
- return ret;
- }
- + (void)delete:(NSString *)service {
- NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
- SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
- }
- @end
- 使用
- static NSString * const KEY_IN_KEYCHAIN = @"com.wuqian.app.allinfo";
- static NSString * const KEY_PASSWORD = @"com.wuqian.app.password";
- +(void)savePassWord:(NSString *)password
- {
- NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionary];
- [usernamepasswordKVPairs setObject:password forKey:KEY_PASSWORD];
- [WQKeyChain save:KEY_IN_KEYCHAIN data:usernamepasswordKVPairs];
- }
- +(id)readPassWord
- {
- NSMutableDictionary *usernamepasswordKVPair = (NSMutableDictionary *)[WQKeyChain load:KEY_IN_KEYCHAIN];
- return [usernamepasswordKVPair objectForKey:KEY_PASSWORD];
- }
- +(void)deletePassWord
- {
- [WQKeyChain delete:KEY_IN_KEYCHAIN];
- }
2.对象归档
“归档”是值另一种形式的序列化,对模型对象进 行归档的技术可以轻松将复杂的对象写入文件, 然后再从中读取它们.
首先看一下简单字符串的归档
保存
NSArray * paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString * myDocumentPath=[paths objectAtIndex:0];
NSString * filename=[myDocumentPath stringByAppendingPathComponent:@"myDefault.txt"];
NSMutableData *data=[NSMutableData data];
NSKeyedArchiver * keyarchive=[[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
if (![self.name isEqualToString:@""] &&![self.number isEqualToString:@""]) {
[keyarchive encodeObject:self.name forKey:@"name"];
[keyarchive encodeObject:self.number forKey:@"number"];
[keyarchive finishEncoding];
[data writeToFile:filename atomically:YES];
[keyarchive release];
}
读取
NSArray * paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString * myDocumentPath=[paths objectAtIndex:0];
NSString * filename=[myDocumentPath stringByAppendingPathComponent:@"myDefault.txt"];
NSMutableData *data=[NSMutableData data];
data=[NSData dataWithContentsOfFile:filename];
if (data.length>0) {
NSKeyedUnarchiver *keyarchive=[[NSKeyedUnarchiver alloc] initForReadingWithData:data];
self.shoujianren.text=(NSString *)[keyarchive decodeObjectForKey:@"name"];
self.name=(NSString *)[keyarchive decodeObjectForKey:@"name"];
self.number=(NSString *)[keyarchive decodeObjectForKey:@"number"];
[keyarchive finishDecoding];
[keyarchive release];
}
如果这里保存的是一个对象,为了保证对象的独立性不能直接保存,要复制一个保存进去。这时候要用到
两个协议 NSCopying ,NSCoding
把一个学生的的信息保存到文件里
1.首先要有一类,实现以上两个协议
#import <Foundation/Foundation.h>
@interface Student : NSObject<NSCoding,NSCopying>
{
NSString *stunumber;
NSString *stuname;
NSString *stumyclass;
}
@property (nonatomic,copy)NSString *stunumber;
@property (nonatomic,copy)NSString *stuname;
@property (nonatomic,copy)NSString *stumyclass;
@end
重写协议里的方法
#import "Student.h"
@implementation Student
@synthesize stuname;
@synthesize stunumber;
@synthesize stumyclass;
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.stumyclass forKey:@"stumyclass"];
[aCoder encodeObject:self.stuname forKey:@"stuname"];
[aCoder encodeObject:self.stunumber forKey:@"stunumber"];
}
- (id)initWithCoder:(NSCoder *)aDecoder{
self.stumyclass=[aDecoder decodeObjectForKey:@"stumyclass"];
self.stuname=[aDecoder decodeObjectForKey:@"stuname"];
self.stunumber=[aDecoder decodeObjectForKey:@"stunumber"];
return self;
}
- (id)copyWithZone:(NSZone *)zone{
Student * copy=[[[self class] allocWithZone:zone] init];
copy.stuname=[self.stuname copyWithZone:zone];
copy.stumyclass=[self.stumyclass copyWithZone:zone];
copy.stunumber=[self.stunumber copyWithZone: zone];
return copy;
}
@end
开始调用
- (IBAction)savewithencdoing:(id)sender {
NSString *mydocumentPath=[[NSBundle mainBundle] bundlePath];
NSString * mydocument=[mydocumentPath stringByAppendingPathComponent:@"student.archive"];
NSMutableData * data=[NSMutableData data];
//文件缓冲
NSKeyedArchiver *keyarchive=[[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
Student *stu=[[Student alloc] init];
stu.stumyclass=self.myClass.text;
stu.stuname=self.myName.text;
stu.stunumber=self.myNumber.text;
Student *mystu=[stu copy]; //这时候会调用协议里的copyWithZone:(NSZone *)zone 方法
[keyarchive encodeObject:mystu forKey:@"mystu"];//这时候会调用encodeWithCoder:(NSCoder *)aCoder
[keyarchive finishEncoding];
[data writeToFile:mydocument atomically:YES];
[stu release];
[keyarchive release];
}
读取
- (IBAction)loadingwithencoding:(id)sender {
// NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// NSString *mydocumentPath=[paths objectAtIndex:0];
//NSString *mydocumentPath=NSTemporaryDirectory();
NSString *mydocumentPath=[[NSBundle mainBundle] bundlePath];
NSString * mydocument=[mydocumentPath stringByAppendingPathComponent:@"student.archive"];
NSMutableData * data=[NSMutableData data];
data=[NSData dataWithContentsOfFile:mydocument];
if(data.length>0){
NSKeyedUnarchiver *keyarchive=[[NSKeyedUnarchiver alloc] initForReadingWithData:data];
Student * stu=[[[Student alloc] init] autorelease];
stu=(Student*)[keyarchive decodeObjectForKey:@"mystu"];
self.myNumber.text=stu.stunumber;
self.myName.text=stu.stuname;
self.myClass.text=stu.stumyclass;
[keyarchive finishDecoding];
[keyarchive release];
//[stu release];
}
}