在iOS中,实现数据持久化一般分为4大种:

1、属性列表

2、对象归档

3、SQLite

4、Core Data

一、属性列表

NSUserDefaults类的使用和NSKeyedArchiver有很多类似之处,但是查看NSUserDefaults的定义可以看出,NSUserDefaults直接继承自NSObject而NSKeyedArchiver继承自NSCoder.这意味着NSKeyedArchiver实际上是个归档类持久化的类,也就是可以使用NSCoder类的[encodeObject:(id)obj forKey:(NSString *)key]方法来数据持久化。

1、创建NSUserDefaults对象

  1. NSUserDefaults *mySettingData = [NSUserDefaults standardUserDefaults];

2、创建NSUserDefaults对象之后即可往里面添加数据,它支持的数据类型有NSString,NSNumber,NSDate、NSArray、NSDictionary、BOOL、NSInteger、NSFloat等系统定义的数据类型,如果要存放自定义的对象,则必须将其转换为NSData类型。

  1. NSArray *arr = [[NSArray alloc] initWithObjects:@"arr1", @"arr2", nil]
  2. [mySettingData setObject:arr forKey:@"arrItem"];
  3. [mySettingData setObject:@"admin" forKey:@"user_name"];
  4. [mySettingData setBOOL:@YES forKey:@"auto_login"];
  5. [mySettingData setInteger:1 forKey:@"count"];

3、往NSUserDefaults添加数据后,它们就变成了全局的变量,App中即可读写NSUserDefaults中的数据。

  1. NSUserDefaults *mySettingDataR = [NSUserDefaults standardUserDefaults];
  2.  
  3. NSLog(@"arrItem=%@", [mySettingDataR objectForKey:@"arrItem"]);
  4. NSLog(@"user_name=%@", [mySettingDataR objectForKey:@"user_name"]);
  5. NSLog(@"count=%d", [mySettingDataR integerForKey:@"count"]);

4、如果想删除某个数据项,可以使用removeObjectForKey删除数据

  1. [mySettingData removeObjectForKey:@"arrItem"];

5、需要注意的是,NSUserDefaults是定时把缓存中的数据写入磁盘的,而不是即时写入,为了防止在写完NSUserDefaults后程序退出导致的数据丢失,可以在写入数据后使用synchronize强制立即将数据写入磁盘:

  1. [mySettingData synchronize];

运行上面得语句后,NSUserDefaults中的数据被写入到.plist文件中,如果是在模拟器上运行程序,可以在Mac的/Users/YOUR-USERNAME/Library/Application Support/iPhone Simulator/4.1/Applications/YOUR-APP-DIR/Library/Prefereces目录下找到一个文件名为YOUR-Bundle_Identifier.plist的plist文件,用Xcode打开该文件,可以看到刚才写入的数据。


二、对象归档  

要使用对象归档,对象必须实现NSCoding协议,大部分OC对象都符合NSCoding协议,也可以在自定义对象中实现NSCoding协议,要实现NSCoding协议,需实现两个方法:

- (void) encodeWithCoder:(NSCoder *)encoder 与 -(void)initWithCoder:(NSCoder *)encoder

同时、建议对象也同时实现NSCopying协议,该协议允许复制对象,要实现NSCopying协议需实现 -(id)copyWithZone:(NSZone *)zone 方法

  1. @interface User : NSObject <NSCoding>
  2. @property (nonatomic, assign) NSInteger userID;
  3. @property (nonatomic, copy) NSString *name;
  4. @end
  5.  
  6. @implementation User
  7. // 以下两个方法一定要实现,不然在调用的时候会crash
  8. - (void)encodeWithCoder:(NSCoder *)aCoder;
  9. {
  10. // 这里放置需要持久化的属性
  11. [aCoder encodeObject:[NSNumber numberWithInteger:self.userID] forKey:@”userID”];
  12. [aCoder encodeObject:self.name forKey:@"name"];
  13. }
  14. - (id)initWithCoder:(NSCoder *)aDecoder
  15. {
  16. if (self = [self init])
  17. {
  18. // 这里务必和encodeWithCoder方法里面的内容一致,不然会读不到数据
  19. self.userID = [[aDecoder decodeObjectForKey:@"userID"] integerValue];
  20. self.name = [aDecoder decodeObjectForKey:@"name"];
  21. }
  22. return self;
  23. }
  24.  
  25. // 使用方法
  26. + (BOOL)save {
  27. NSError *error = nil;
  28. // 确定存储路径,一般是Document目录下的文件
  29. NSString* fileName = [self getFileName];
  30. NSString* filePath = [self getFilePath];
  31. if (![[NSFileManager defaultManager] createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:&error]) {
  32. NSLog(@”创建用户文件目录失败”);
  33. return NO;
  34. }
  35. return [NSKeyedArchiver archiveRootObject:self toFile:[fileName:userId]];
  36. }
  37. @end

三、SQLite 

准备工作:导入相关库文件:libsqlit3.dylib。

使用:

1、创建数据库并打开:

  1. /**
  2. * 打开数据库并创建一个表
  3. */
  4. - (void)openDatabase {
  5. //1.设置文件名
  6. NSString *filename = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.db"];
  7. //2.打开数据库文件,如果没有会自动创建一个文件
  8. NSInteger result = sqlite3_open(filename.UTF8String, &_sqlite3);
  9. if (result == SQLITE_OK) {
  10. NSLog(@"打开数据库成功!");
  11. //3.创建一个数据库表
  12. char *errmsg = NULL;
  13. sqlite3_exec(_sqlite3, "CREATE TABLE IF NOT EXISTS t_person(id integer primary key autoincrement, name text, age integer)", NULL, NULL, &errmsg);
  14. if (errmsg) {
  15. NSLog(@"错误:%s", errmsg);
  16. } else {
  17. NSLog(@"创表成功!");
  18. }
  19. } else {
  20. NSLog(@"打开数据库失败!");
  21. }
  22. }

2、执行语句。使用sqlite3_exec()方法可以执行任何SQL语句,比如创建表、更新、插入、删除操作。

  1. /**
  2. * 往表中插入1000条数据
  3. */
  4. - (void)insertData {
  5. NSString *nameStr;
  6. NSInteger age;
  7. for (NSInteger i = 0; i < 1000; i++) {
  8. nameStr = [NSString stringWithFormat:@"Bourne-%d", arc4random_uniform(10000)];
  9. age = arc4random_uniform(80) + 20;
  10. NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_person (name, age) VALUES('%@', '%ld')", nameStr, age];
  11. char *errmsg = NULL;
  12. sqlite3_exec(_sqlite3, sql.UTF8String, NULL, NULL, &errmsg);
  13. if (errmsg) {
  14. NSLog(@"错误:%s", errmsg);
  15. }
  16. }
  17. NSLog(@"插入完毕!");
  18. }

一般不使用 sqlite3_exec() 方法查询数据。因为查询数据必须要获得查询结果,所以查询相对比较麻烦。示例代码如下: 

  1. /**
  2. * 从表中读取数据到数组中
  3. */
  4. - (void)readData {
  5. NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:1000];
  6. char *sql = "select name, age from t_person;";
  7. sqlite3_stmt *stmt;
  8. NSInteger result = sqlite3_prepare_v2(_sqlite3, sql, -1, &stmt, NULL);
  9. if (result == SQLITE_OK) {
  10. while (sqlite3_step(stmt) == SQLITE_ROW) {
  11. char *name = (char *)sqlite3_column_text(stmt, 0);
  12. NSInteger age = sqlite3_column_int(stmt, 1);
  13. //创建对象
  14. Person *person = [Person personWithName:[NSString stringWithUTF8String:name] Age:age];
  15. [mArray addObject:person];
  16. }
  17. self.dataList = mArray;
  18. }
  19. sqlite3_finalize(stmt);
  20. }

总体来说,使用SQLite比较麻烦,因为里面都是一些C语言函数。在开发中,一般不使用SQLite,而是使用第三方开源库FMDB,DMDB封装了SQLite。

FMDB

1.简介

FMDB是iOS平台的SQLite数据库框架,它是以OC的方式封装了SQLite的C语言API,它相对于cocoa自带的C语言框架有如下的优点:

使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码

对比苹果自带的Core Data框架,更加轻量级和灵活

提供了多线程安全的数据库操作方法,有效地防止数据混乱

注:FMDB的gitHub地址

2.核心类

FMDB有三个主要的类:

  • FMDatabase

一个FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句

  • FMResultSet

使用FMDatabase执行查询后的结果集

  • FMDatabaseQueue

用于在多线程中执行多个查询或更新,它是线程安全的

3.打开数据库

和c语言框架一样,FMDB通过指定SQLite数据库文件路径来创建FMDatabase对象,但FMDB更加容易理解,使用起来更容易,使用之前一样需要导入sqlite3.dylib。打开数据库方法如下:

1
2
3
4
5
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.db"];
FMDatabase *database = [FMDatabase databaseWithPath:path];    
if (![database open]) {
    NSLog(@"数据库打开失败!");
}

值得注意的是,Path的值可以传入以下三种情况:

  • 具体文件路径,如果不存在会自动创建

  • 空字符串@"",会在临时目录创建一个空的数据库,当FMDatabase连接关闭时,数据库文件也被删除

  • nil,会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁

4.更新

在FMDB中,除查询以外的所有操作,都称为“更新”, 如:create、drop、insert、update、delete等操作,使用executeUpdate:方法执行更新:

1
2
3
4
5
6
7
8
//常用方法有以下3种:   
- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
//示例
[database executeUpdate:@"CREATE TABLE IF NOT EXISTS t_person(id integer primary key autoincrement, name text, age integer)"];   
//或者  
[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES(?, ?)", @"Bourne", [NSNumber numberWithInt:42]];

5.查询

查询方法也有3种,使用起来相当简单:

1
2
3
- (FMResultSet *)executeQuery:(NSString*)sql, ...
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments

查询示例:

1
2
3
4
5
6
7
//1.执行查询
FMResultSet *result = [database executeQuery:@"SELECT * FROM t_person"];
//2.遍历结果集
while ([result next]) {
    NSString *name = [result stringForColumn:@"name"];
    int age = [result intForColumn:@"age"];
}

6.线程安全

在多个线程中同时使用一个FMDatabase实例是不明智的。不要让多个线程分享同一个FMDatabase实例,它无法在多个线程中同时使用。 如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题。所以,请使用 FMDatabaseQueue,它是线程安全的。以下是使用方法:

  • 创建队列。

1
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
  • 使用队列

1
2
3
4
5
6
7
8
[queue inDatabase:^(FMDatabase *database) {    
          [database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_1", [NSNumber numberWithInt:1]];    
          [database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_2", [NSNumber numberWithInt:2]];    
          [database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_3", [NSNumber numberWithInt:3]];      
          FMResultSet *result = [database executeQuery:@"select * from t_person"];    
         while([result next]) {   
         }    
}];

而且可以轻松地把简单任务包装到事务里:

1
2
3
4
5
6
7
8
9
10
[queue inTransaction:^(FMDatabase *database, BOOL *rollback) {    
          [database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_1", [NSNumber numberWithInt:1]];    
          [database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_2", [NSNumber numberWithInt:2]];    
          [database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_3", [NSNumber numberWithInt:3]];      
          FMResultSet *result = [database executeQuery:@"select * from t_person"];    
             while([result next]) {   
             }   
           //回滚
           *rollback = YES;  
    }];

CoreData

Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句,这个有点类似于著名的Hibernate持久化框架,不过功能肯定是没有Hibernate强大的。简单地用下图描述下它的作用:

左边是关系模型,即数据库,数据库里面有张person表,person表里面有id、name、age三个字段,而且有2条记录;

右边是对象模型,可以看到,有2个OC对象;

利用Core Data框架,我们就可以轻松地将数据库里面的2条记录转换成2个OC对象,也可以轻松地将2个OC对象保存到数据库中,变成2条表记录,而且不用写一条SQL语句。

CoreData的简单使用

准备工作

  • 创建数据库

    1. 新建文件,选择CoreData -> DataModel
    2. 添加实体(表),Add Entity
    3. 给表中添加属性,点击Attributes下方的‘+’
  • 创建模型文件

    1. 新建文件,选择CoreData -> NSManaged Object subclass
    2. 根据提示,选择实体
  • 通过代码,关联数据库和实体

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. /*
    4. * 关联的时候,如果本地没有数据库文件,Coreadata自己会创建
    5. */
    6. // 1. 上下文
    7. NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
    8. // 2. 上下文关连数据库
    9. // 2.1 model模型文件
    10. NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
    11. // 2.2 持久化存储调度器
    12. // 持久化,把数据保存到一个文件,而不是内存
    13. NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    14. // 2.3 设置CoreData数据库的名字和路径
    15. NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    16. NSString *sqlitePath = [doc stringByAppendingPathComponent:@"company.sqlite"];
    17. [store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:sqlitePath] options:nil error:nil];
    18. context.persistentStoreCoordinator = store;
    19. _context = context;
    20. }

CoreData的基本操作(CURD)

  • 添加元素 - Create

    1. -(IBAction)addEmployee{
    2. // 创建一个员工对象
    3. //Employee *emp = [[Employee alloc] init]; 不能用此方法创建
    4. Employee *emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:_context];
    5. emp.name = @"wangwu";
    6. emp.height = @1.80;
    7. emp.birthday = [NSDate date];
    8. // 直接保存数据库
    9. NSError *error = nil;
    10. [_context save:&error];
    11. if (error) {
    12. NSLog(@"%@",error);
    13. }
    14. }
  • 读取数据 - Read

    1. -(IBAction)readEmployee{
    2. // 1.FetchRequest 获取请求对象
    3. NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    4. // 2.设置过滤条件
    5. // 查找zhangsan
    6. NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@",
    7. @"zhangsan"];
    8. request.predicate = pre;
    9. // 3.设置排序
    10. // 身高的升序排序
    11. NSSortDescriptor *heigtSort = [NSSortDescriptor sortDescriptorWithKey:@"height" ascending:NO];
    12. request.sortDescriptors = @[heigtSort];
    13. // 4.执行请求
    14. NSError *error = nil;
    15. NSArray *emps = [_context executeFetchRequest:request error:&error];
    16. if (error) {
    17. NSLog(@"error");
    18. }
    19. //NSLog(@"%@",emps);
    20. //遍历员工
    21. for (Employee *emp in emps) {
    22. NSLog(@"名字 %@ 身高 %@ 生日 %@",emp.name,emp.height,emp.birthday);
    23. }
    24. }
  • 修改数据 - Update

    1. -(IBAction)updateEmployee{
    2. // 改变zhangsan的身高为2m
    3. // 1.查找到zhangsan
    4. // 1.1FectchRequest 抓取请求对象
    5. NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    6. // 1.2设置过滤条件
    7. // 查找zhangsan
    8. NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@", @"zhangsan"];
    9. request.predicate = pre;
    10. // 1.3执行请求
    11. NSArray *emps = [_context executeFetchRequest:request error:nil];
    12. // 2.更新身高
    13. for (Employee *e in emps) {
    14. e.height = @2.0;
    15. }
    16. // 3.保存
    17. NSError *error = nil;
    18. [_context save:&error];
    19. if (error) {
    20. NSLog(@"%@",error);
    21. }
    22. }
  • 删除数据 - Delete

    1. -(IBAction)deleteEmployee{
    2. // 删除 lisi
    3. // 1.查找lisi
    4. // 1.1FectchRequest 抓取请求对象
    5. NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    6. // 1.2设置过滤条件
    7. // 查找zhangsan
    8. NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@",
    9. @"lisi"];
    10. request.predicate = pre;
    11. // 1.3执行请求
    12. NSArray *emps = [_context executeFetchRequest:request error:nil];
    13. // 2.删除
    14. for (Employee *e in emps) {
    15. [_context deleteObject:e];
    16. }
    17. // 3.保存
    18. NSError *error = nil;
    19. [_context save:&error];
    20. if (error) {
    21. NSLog(@"%@",error);
    22. }
    23. }

CoreData的表关联

准备工作

  • 创建数据库

    1. 新建文件,选择CoreData -> DataModel
    2. 添加实体(表),Add Entity , 注意:这里根据关联添加多个实体
    3. 给表中添加属性,点击Attributes下方的‘+’
  • 创建模型文件

    1. 新建文件,选择CoreData -> NSManaged Object subclass
    2. 根据提示,选择实体,注意:这里先选择被关联的实体,最后添加最上层的实体
  • 通过代码,关联数据库和实体

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. /*
    4. * 关联的时候,如果本地没有数据库文件,Coreadata自己会创建
    5. */
    6. // 1. 上下文
    7. NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
    8. // 2. 上下文关连数据库
    9. // 2.1 model模型文件
    10. NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
    11. // 2.2 持久化存储调度器
    12. // 持久化,把数据保存到一个文件,而不是内存
    13. NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    14. // 2.3 设置CoreData数据库的名字和路径
    15. NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    16. NSString *sqlitePath = [doc stringByAppendingPathComponent:@"company.sqlite"];
    17. [store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:sqlitePath] options:nil error:nil];
    18. context.persistentStoreCoordinator = store;
    19. _context = context;
    20. }

基本操作

  • 添加元素 - Create

    1. -(IBAction)addEmployee{
    2. // 1. 创建两个部门 ios android
    3. //1.1 iOS部门
    4. Department *iosDepart = [NSEntityDescription insertNewObjectForEntityForName:@"Department" inManagedObjectContext:_context];
    5. iosDepart.name = @"ios";
    6. iosDepart.departNo = @"0001";
    7. iosDepart.createDate = [NSDate date];
    8. //1.2 Android部门
    9. Department *andrDepart = [NSEntityDescription insertNewObjectForEntityForName:@"Department" inManagedObjectContext:_context];
    10. andrDepart.name = @"android";
    11. andrDepart.departNo = @"0002";
    12. andrDepart.createDate = [NSDate date];
    13. //2. 创建两个员工对象 zhangsan属于ios部门 lisi属于android部门
    14. //2.1 zhangsan
    15. Employee *zhangsan = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:_context];
    16. zhangsan.name = @"zhangsan";
    17. zhangsan.height = @(1.90);
    18. zhangsan.birthday = [NSDate date];
    19. zhangsan.depart = iosDepart;
    20. //2.2 lisi
    21. Employee *lisi = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:_context];
    22. lisi.name = @"lisi";
    23. lisi.height = @2.0;
    24. lisi.birthday = [NSDate date];
    25. lisi.depart = andrDepart;
    26. //3. 保存数据库
    27. NSError *error = nil;
    28. [_context save:&error];
    29. if (error) {
    30. NSLog(@"%@",error);
    31. }
    32. }
  • 读取信息 - Read

    1. -(IBAction)readEmployee{
    2. // 读取ios部门的员工
    3. // 1.FectchRequest 抓取请求对象
    4. NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    5. // 2.设置过滤条件
    6. NSPredicate *pre = [NSPredicate predicateWithFormat:@"depart.name = %@",@"android"];
    7. request.predicate = pre;
    8. // 4.执行请求
    9. NSError *error = nil;
    10. NSArray *emps = [_context executeFetchRequest:request error:&error];
    11. if (error) {
    12. NSLog(@"error");
    13. }
    14. //遍历员工
    15. for (Employee *emp in emps) {
    16. NSLog(@"名字 %@ 部门 %@",emp.name,emp.depart.name);
    17. }
    18. }
  • 其他功能与前几种类似,这里不在赘述

CoreData的模糊查询

准备工作和上面类似,主要是查询方式不同

  • 模糊查询

    1. -(IBAction)readEmployee{
    2. // 1.FectchRequest 抓取请求对象
    3. NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    4. // 2.设置排序
    5. // 按照身高的升序排序
    6. NSSortDescriptor *heigtSort = [NSSortDescriptor sortDescriptorWithKey:@"height" ascending:NO];
    7. request.sortDescriptors = @[heigtSort];
    8. // 3.模糊查询
    9. // 3.1 名字以"wang"开头
    10. // NSPredicate *pre = [NSPredicate predicateWithFormat:@"name BEGINSWITH %@",@"wangwu1"];
    11. // request.predicate = pre;
    12. // 名字以"1"结尾
    13. // NSPredicate *pre = [NSPredicate predicateWithFormat:@"name ENDSWITH %@",@"1"];
    14. // request.predicate = pre;
    15. // 名字包含"wu1"
    16. // NSPredicate *pre = [NSPredicate predicateWithFormat:@"name CONTAINS %@",@"wu1"];
    17. // request.predicate = pre;
    18. // like 匹配
    19. NSPredicate *pre = [NSPredicate predicateWithFormat:@"name like %@",@"*wu12"];
    20. request.predicate = pre;
    21. // 4.执行请求
    22. NSError *error = nil;
    23. NSArray *emps = [_context executeFetchRequest:request error:&error];
    24. if (error) {
    25. NSLog(@"error");
    26. }
    27. //遍历员工
    28. for (Employee *emp in emps) {
    29. NSLog(@"名字 %@ 身高 %@ 生日 %@",emp.name,emp.height,emp.birthday);
    30. }
    31. }
  • 分页查询

    1. -(void)pageSeacher{
    2. // 1. FectchRequest 抓取请求对象
    3. NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    4. // 2. 设置排序
    5. // 身高的升序排序
    6. NSSortDescriptor *heigtSort = [NSSortDescriptor sortDescriptorWithKey:@"height" ascending:NO];
    7. request.sortDescriptors = @[heigtSort];
    8. // 3. 分页查询
    9. // 总有共有15数据
    10. // 每次获取6条数据
    11. // 第一页 0,6
    12. // 第二页 6,6
    13. // 第三页 12,6 3条数据
    14. // 3.1 分页的起始索引
    15. request.fetchOffset = 12;
    16. // 3.2 分页的条数
    17. request.fetchLimit = 6;
    18. // 4. 执行请求
    19. NSError *error = nil;
    20. NSArray *emps = [_context executeFetchRequest:request error:&error];
    21. if (error) {
    22. NSLog(@"error");
    23. }
    24. // 5. 遍历员工
    25. for (Employee *emp in emps) {
    26. NSLog(@"名字 %@ 身高 %@ 生日 %@",emp.name,emp.height,emp.birthday);
    27. }
    28. }

多个数据库的使用

注意:

创建多个数据库,即创建多个DataModel
一个数据库对应一个上下文
需要根据bundle名创建上下文
添加或读取信息,需要根据不同的上下文,访问不同的实体

  • 关联数据库和实体

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. // 一个数据库对应一个上下文
    4. _companyContext = [self setupContextWithModelName:@"Company"];
    5. _weiboContext = [self setupContextWithModelName:@"Weibo"];
    6. }
    7. /**
    8. * 根据模型文件,返回一个上下文
    9. */
    10. -(NSManagedObjectContext *)setupContextWithModelName:(NSString *)modelName{
    11. // 1. 上下文
    12. NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
    13. // 2. 上下文关连数据库
    14. // 2.1 model模型文件
    15. // 注意:如果使用下面的方法,如果 bundles为nil 会把bundles里面的所有模型文件的表放在一个数据库
    16. //NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
    17. // 改为以下的方法获取:
    18. NSURL *companyURL = [[NSBundle mainBundle] URLForResource:modelName withExtension:@"momd"];
    19. NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:companyURL];
    20. // 2.2 持久化存储调度器
    21. // 持久化,把数据保存到一个文件,而不是内存
    22. NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    23. // 2.3 告诉Coredata数据库的名字和路径
    24. NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    25. NSString *sqliteName = [NSString stringWithFormat:@"%@.sqlite",modelName];
    26. NSString *sqlitePath = [doc stringByAppendingPathComponent:sqliteName];
    27. [store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:sqlitePath] options:nil error:nil];
    28. context.persistentStoreCoordinator = store;
    29. // 3. 返回上下文
    30. return context;
    31. }
  • 添加元素

    1. -(IBAction)addEmployee{
    2. // 1. 添加员工
    3. Employee *emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:_companyContext];
    4. emp.name = @"zhagsan";
    5. emp.height = @2.3;
    6. emp.birthday = [NSDate date];
    7. // 直接保存数据库
    8. [_companyContext save:nil];
    9. // 2. 发微博
    10. Status *status =[NSEntityDescription insertNewObjectForEntityForName:@"Status" inManagedObjectContext:_weiboContext];
    11. status.text = @"发了一条微博!";
    12. status.createDate = [NSDate date];
    13. [_weiboContext save:nil];
    14. }

 

iOS数据持久化的更多相关文章

  1. iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

  2. iOS开发笔记-swift实现iOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (plist.NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data.第三方类库等 归档(又名 ...

  3. IOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (自定义的Property List .NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data ...

  4. iOS -数据持久化方式-以真实项目讲解

    前面已经讲解了SQLite,FMDB以及CoreData的基本操作和代码讲解(CoreData也在不断学习中,上篇博客也会不断更新中).本篇我们将讲述在实际开发中,所使用的iOS数据持久化的方式以及怎 ...

  5. iOS数据持久化方式及class_copyIvarList与class_copyPropertyList的区别

    iOS数据持久化方式:plist文件(属性列表)preference(偏好设置)NSKeyedArchiver(归档)SQLite3CoreData沙盒:iOS程序默认情况下只能访问自己的程序目录,这 ...

  6. iOS数据持久化-OC

    沙盒详解 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文 ...

  7. iOS数据持久化存储:归档

    在平时的iOS开发中,我们经常用到的数据持久化存储方式大概主要有:NSUserDefaults(plist),文件,数据库,归档..前三种比较经常用到,第四种归档我个人感觉用的还是比较少的,恰恰因为用 ...

  8. 转载 -- iOS数据持久化存储

    作者:@翁呀伟呀 授权本站转载 概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方 ...

  9. iOS 数据持久化(1):属性列表与对象归档

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css); @import url(/ ...

随机推荐

  1. Remove Duplicates from Sorted Array [LeetCode]

    Given a sorted array, remove the duplicates in place such that each element appear only once and ret ...

  2. 聚类算法:ISODATA算法

    1. 与K-均值算法的比较 –K-均值算法通常适合于分类数目已知的聚类,而ISODATA算法则更加灵活: –从算法角度看, ISODATA算法与K-均值算法相似,聚类中心都是通过样本均值的迭代运算来决 ...

  3. Objective-C:Foundation框架-常用类-NSNull

    集合中是不能存储nil值的,因为nil在集合中有特殊含义,但有时确实需要存储一个表示“什么都没有”的值,那么可以使用NSNull,它也是NSObject的一个子类. #import <Found ...

  4. for循环语句以及迭代法和穷举法

    循环语句: 四要素:初始条件,循环条件,状态改变,循环体 for(初始条件;循环条件;状态改变){ //循环体} 案例1:打印等腰直角三角形和菱形 左上三角 static void Main(stri ...

  5. Java多线程-新特征-锁(上)

    在Java5中,专门提供了锁对象,利用锁可以方便的实现资源的封锁,用来控制对竞争资源并发访问的控制,这些内容主要集中在java.util.concurrent.locks 包下面,里面有三个重要的接口 ...

  6. BZOJ3993 [SDOI2015]星际战争

    二分答案...然后最大流验证是否可行... 没了,好水啊QAQ /************************************************************** Prob ...

  7. 亿级Web系统搭建——单机到分布式集群[转]

    当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题.为了解决这些性能压力带来问题,我们需要在Web系统架构层 ...

  8. 浅谈C++源码的过国内杀软的免杀

    以下只是简单的思路和定位.也许有人秒过,但是不要笑话我写的笨方法.定位永远是过期不了的. 其实这里废话一下 , 本人并不是大牛 ,今天跟大家分享下 .所以写出这篇文章.(大牛飘过) 只是个人实战的经验 ...

  9. mysql给定一个随机数

    )) 给定一个1-50中间的随机数

  10. [转载]Android 异步加载解决方案

    2013-12-25 11:15:47 Android 异步加载解决方案,转载自: http://www.open-open.com/lib/view/open1345017746897.html 请 ...