标签:
概论
数据持久化存储:所谓持久化存储就是将数据保存到硬盘中,使得应用程序或者机器在重启后可以访问之前保存的数据。
常见方式:
沙盒
说到持久化存储就不得不说一下苹果的沙盒机制,苹果的一个应用程序就对应一个沙盒。
这样做的好处有以下几点:
那怎么打开沙盒呢?
进入沙盒之后我们能看到三个文件夹:
*Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除
*Preferences:偏好设置是专门用来保存应用程序的配置信息的,一般不要在偏好设置中保存其他数据。
iTunes在与iPhone同步时,备份所有的Documents和Library文件。
iPhone在重启时,会丢弃所有的tmp文件。
那我们怎么在程序中得到这些路径呢?
Document:
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; NSLog(@"%@", documentPath);
Library/Caches:
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject; NSLog(@"%@", cachePath);
tmp:
NSString *tmpPath = NSTemporaryDirectory(); NSLog(@"%@", tmpPath);
plist文件
plist就是将某些特定的类,通过XML方式保存在目录中。
可以被序列化的类型只有以下几种:(其中根结点必须是NSArray或者NSDictionary)
NSArray;
NSMutableArray;
NSDictionary;
NSMutableDictionary;
NSData;
NSMutableData;
NSString;
NSMutableString;
NSNumber;
NSDate;
BOOL
//获取文件路径 NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; NSString *fileName = [documentPath stringByAppendingPathComponent:@"file.plist"]; //存储 NSArray *array = @[@{@"字典":@"dict"}, @YES, @"string", @(10), ]; [array writeToFile:fileName atomically:YES]; //读取 NSArray *resultArray = [NSArray arrayWithContentsOfFile:fileName]; NSLog(@"%@",resultArray);
Preference:偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件。
//1.获得NSUserDefaults文件 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; //2.向文件中写入内容 [userDefaults setObject:@"wuhongxing" forKey:@"name"]; [userDefaults setBool:YES forKey:@"sex"]; [userDefaults setInteger:21 forKey:@"age"]; //2.1立即同步 [userDefaults synchronize]; //3.读取文件 NSString *name = [userDefaults objectForKey:@"name"]; BOOL sex = [userDefaults boolForKey:@"sex"]; NSInteger age = [userDefaults integerForKey:@"age"]; NSLog(@"%@, %d, %ld", name, sex, age);
NSKeyedArchiver:归档在iOS中是另一种形式的序列化,只要遵循了NSCoding协议的对象都可以通过它实现序列化
1.遵循NSCoding协议
@interface Person : NSObject <NSCoding> /**名字*/ @property (nonatomic, copy) NSString *name; /**年龄*/ @property (nonatomic, assign) NSInteger age; /**头像*/ @property (nonatomic, strong) UIImage *avatar; @end
2.实现NSCoding协议
//归档 - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:_avatar forKey:@"avatar"]; [aCoder encodeObject:_name forKey:@"name"]; [aCoder encodeInteger:_age forKey:@"age"]; } //解档 - (instancetype)initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { self.avatar = [aDecoder decodeObjectForKey:@"avatar"]; self.name = [aDecoder decodeObjectForKey:@"name"]; self.age = [aDecoder decodeIntegerForKey:@"age"]; } return self; }
特别注意:如果归档的类是某个自定义类的子类,就需要在归档和解档之前先实现父类的归档和解档方法。即 [super encodeWithCoder:aCoder] 和 [super initWithCoder:aDecoder] 方法;
3.使用
//需要把对象归档是调用NSKeyedArchiver的工厂方法 archiveRootObject: toFile: 方法。 NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"]; Person *per = [[Person alloc] init]; per.name = @"whx"; per.age = 24; per.avatar = UIImagePNGRepresentation([UIImage imageNamed:@"tab_accountH"]); [NSKeyedArchiver archiveRootObject:per toFile:documentPath]; //需要从文件中解档对象就调用NSKeyedUnarchiver的一个工厂方法 unarchiveObjectWithFile: 即可。 Person *resultPer = [NSKeyedUnarchiver unarchiveObjectWithFile:documentPath]; if (resultPer) { NSLog(@"%@ %li %@",resultPer.name,resultPer.age,[UIImage imageWithData:per.avatar]); }
SQLite3:之前的所有存储方法,都是覆盖存储。如果想要增加一条数据就必须把整个文件读出来,然后修改数据后再把整个内容覆盖写入文件。所以它们都不适合存储大量的内容。
1.字段类型
表面上SQLite将数据分为以下几种类型:
integer : 整数
real : 实数(浮点数)
text : 文本字符串
blob : 二进制数据,比如文件,图片之类的
实际上SQLite是无类型的。即不管你在创表时指定的字段类型是什么,存储是依然可以存储任意类型的数据。而且在创表时也可以不指定字段类型。SQLite之所以什么类型就是为了良好的编程规范和方便开发人员交流,所以平时在使用时最好设置正确的字段类型!主键必须设置成integer
2. 准备工作
准备工作就是导入依赖库啦,在iOS中要使用SQLite3,需要添加库文件:libsqlite3.dylib并导入主头文件,这是一个C语言的库,所以直接使用SQLite3还是比较麻烦的。
3.如何使用:数据库涉及到的常见操作有增、删、改、查。
基于FMDB的再封装
1.简介
FMDB是iOS平台的SQLite数据库框架,它是以OC的方式封装了SQLite的C语言API,它相对于cocoa自带的C语言框架有如下的优点:
使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
对比苹果自带的Core Data框架,更加轻量级和灵活
提供了多线程安全的数据库操作方法,有效地防止数据混乱
2.核心类
FMDB有三个主要的类:
FMDatabase
一个FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句
FMResultSet
使用FMDatabase执行查询后的结果集
FMDatabaseQueue
用于在多线程中执行多个查询或更新,它是线程安全的
3.使用:基于FMDB的二次迭代,更加面向对象(先要定义两个全局变量,数据库FMDatabase *_database和NSLock *_lock(为了线程安全,防止两个线程同时修改数据库里的数据))
打开数据库
/** * 构造方法 * * @param path 数据库路径 */ - (instancetype)initWithDataBasePath:(NSString *)path { if (self = [super init]) { _database = [[FMDatabase alloc] initWithPath:path]; //创建线程锁 _lock = [[NSLock alloc] init]; BOOL ret = [_database open]; PERROR(ret, "open"); } return self; }
创建表单
- (void)createTable:(NSString *)tableName primaryKey:(NSString *)keyName primaryType:(NSString *)colType otherColums:(NSDictionary *)colums { [_lock lock]; //加锁 NSMutableString * sql = [NSMutableString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@(%@ %@ PRIMARY KEY", tableName, keyName, colType]; for (NSString * key in colums) { //key是列名 [sql appendFormat:@", %@ %@", key, colums[key]]; } [sql appendString:@");"]; //FMDB会自动添加分号 BOOL ret = [_database executeUpdate:sql]; PERROR(ret, "create table"); [_lock unlock]; //解锁 }
删除表单
/** * 删除表单 * * @param tableName 表单名 */ - (void)dropTable:(NSString *)tableName { [_lock lock]; NSString * sql = [NSString stringWithFormat:@"DROP TABLE %@;", tableName]; BOOL ret = [_database executeUpdate:sql]; PERROR(ret, "drop table"); [_lock unlock]; }
插入数据
/** * 插入数据 * * @param tableName 表单名 * @param dict key:列名 value:列值 */ - (void)insertRecordIntoTable:(NSString *)tableName withColumsAndValues:(NSDictionary *)dict; { [_lock lock]; //拼接列名 NSMutableString * colStr = [NSMutableString string]; //拼接value NSMutableString * valuesStr = [NSMutableString string]; colStr.string = [dict.allKeys componentsJoinedByString:@","]; NSMutableArray * xArray = [NSMutableArray array]; for (NSUInteger i = 0; i < dict.count; i++) { [xArray addObject:@"?"]; } valuesStr.string = [xArray componentsJoinedByString:@","]; //创建SQL NSMutableString * sql = [NSMutableString stringWithFormat:@"INSERT INTO %@(%@) VALUES(%@);", tableName, colStr, valuesStr]; BOOL ret = [_database executeUpdate:sql withArgumentsInArray:dict.allValues]; PERROR(ret, "insert record"); [_lock unlock]; }
拼接筛选的字符串
- (NSString *)whereStringFromWhereDictionary:(NSDictionary *)dict { //拼接删选的字符串 NSMutableArray * whereArray = [NSMutableArray array]; for (NSString * key in dict) { [whereArray addObject:[NSString stringWithFormat:@"%@ = ?", key]]; } NSString * whereStr = [whereArray componentsJoinedByString:@" AND "]; return whereStr; }
删除记录
/** * 删除记录 * * @param tableName 表单名 * @param whereDict 字典,筛选的条件 */ - (void)deleteRecordFromTable:(NSString *)tableName where:(NSDictionary *)whereDict { [_lock lock]; NSString * sql = nil; if (whereDict == nil) { sql = [NSString stringWithFormat:@"DELETE FROM %@", tableName]; BOOL ret = [_database executeUpdate:sql]; PERROR(ret, "delete whereDict"); [_lock unlock]; return; } //拼接筛选字符串 NSString * whereStr = [self whereStringFromWhereDictionary:whereDict]; //拼接SQL sql = [NSString stringWithFormat:@"DELETE FROM %@ WHERE %@", tableName, whereStr]; BOOL ret = [_database executeUpdate:sql withArgumentsInArray:whereDict.allValues]; PERROR(ret, "delete whereDict"); [_lock unlock]; }
/** * 删除记录 * * @param tableName 表单名 * @param whereStr 用户自定议删除条件 */ - (void)deleteRecordFromTable:(NSString *)tableName whereString:(NSString *)whereStr { [_lock lock]; NSString * sql = [NSString stringWithFormat:@"DELETE FROM %@ WHERE %@", tableName, whereStr]; BOOL ret = [_database executeUpdate:sql]; PERROR(ret, "delete whereStr"); [_lock unlock]; }
查找数据
/** * 查看记录 * * @param columNames 数组 * @param tableName 表单名 * @param whereDict 字典 * * @return 查看结果 */ - (FMResultSet *)select:(NSArray *)columNames fromTable:(NSString *)tableName where:(NSDictionary *)whereDict { [_lock lock]; //首先是列的字符串 NSString * colStr = nil; if (columNames == nil) { colStr = @"*"; } else { colStr = [columNames componentsJoinedByString:@","]; } NSString * sql = nil; if (whereDict == nil) { sql = [NSString stringWithFormat:@"SELECT %@ FROM %@", colStr, tableName]; FMResultSet * set = [_database executeQuery:sql]; [_lock unlock]; return set; } //拼接删选字符串 NSString * whereStr = [self whereStringFromWhereDictionary:whereDict]; //拼接SQL sql = [NSString stringWithFormat:@"SELECT %@ FROM %@ WHERE %@", colStr, tableName, whereStr]; FMResultSet * set = [_database executeQuery:sql withArgumentsInArray:whereDict.allValues]; [_lock unlock]; return set; }
拼接更新字符串
//拼接更新的字符串 - (NSString *)updateStringFromUpdateDictionary:(NSDictionary *)dict { //拼接删选的字符串 NSMutableArray * whereArray = [NSMutableArray array]; for (NSString * key in dict) { [whereArray addObject:[NSString stringWithFormat:@"%@ = ?", key]]; } NSString * whereStr = [whereArray componentsJoinedByString:@","]; return whereStr; }
更新记录
/** * 更新记录 * * @param tableName 表单名 * @param updateDict 更新的记录 * @param whereDict 筛选条件 */ - (void)updateTable:(NSString *)tableName records:(NSDictionary *)updateDict where:(NSDictionary *)whereDict { [_lock lock]; //拼接更新的字符串 NSString * updateStr = [self updateStringFromUpdateDictionary:updateDict]; //拼接筛选条件 NSString * sql = nil; if (whereDict == nil) { sql = [NSString stringWithFormat:@"UPDATE %@ SET %@;", tableName, updateStr]; BOOL ret = [_database executeUpdate:sql]; PERROR(ret, "update"); [_lock unlock]; return; } //拼接whereStr NSString * whereStr = [self whereStringFromWhereDictionary:whereDict]; sql = [NSString stringWithFormat:@"UPDATE %@ SET %@ WHERE %@;", tableName, updateStr, whereStr]; //合体的数组 NSArray * compArray = [updateDict.allValues arrayByAddingObjectsFromArray:whereDict.allValues]; BOOL ret = [_database executeUpdate:sql withArgumentsInArray:compArray]; PERROR(ret, "update"); [_lock unlock]; }
使用:
+ (void)test { DataBaseManage * dbm = [[DataBaseManage alloc] initWithDataBasePath:@"/Users/wuhongxing/Desktop/GP03/day18/DataBase/XX.sqlite"]; [dbm dropTable:@"男演员"]; NSDictionary * colums = @{ @"姓名":@"varchar(128)", @"国籍":@"varchar(128)" }; [dbm createTable:@"男演员" primaryKey:@"ID" primaryType:@"integer" otherColums:colums]; [dbm insertRecordIntoTable:@"男演员" withColumsAndValues:@{@"姓名":@"刘德华", @"国籍":@"中国"}]; [dbm insertRecordIntoTable:@"男演员" withColumsAndValues:@{@"姓名":@"郭富城", @"国籍":@"中国"}]; [dbm insertRecordIntoTable:@"男演员" withColumsAndValues:@{@"姓名":@"威尔 史密斯", @"国籍":@"美国"}]; [dbm deleteRecordFromTable:@"男演员" where:@{@"姓名":@"郭富城"}]; [dbm updateTable:@"男演员" records:@{@"姓名":@"周杰伦", @"国籍":@"中国台湾", @"ID":@"2"} where:@{@"姓名":@"威尔 史密斯"}]; FMResultSet * set = [dbm select:nil fromTable:@"男演员" where:nil]; while ([set next]) { //依次循环一条记录 //取出记录中的属性 int ID = [set intForColumn:@"ID"]; NSString * name = [set stringForColumn:@"姓名"]; NSString * contry = [set stringForColumn:@"国籍"]; } }
标签:
原文地址:http://www.cnblogs.com/wuhongxing/p/4988854.html