ios CoreData和FMDB最新使用问题总结

来源:互联网 发布:电视盒子推荐 知乎 编辑:程序博客网 时间:2024/06/09 13:55

1.xcode8 无法创建NSManagedObjectModel subClass和 创建NSManagedObjectModel subClass为swift版本 问题解决见链接   点击打开链接

2.FMDB和CoreData性能问题比较

    1)经过楼主真机测试,大量数据插入(超过1万条) FMDB经过伪批处理之后的性能和CoreData性能旗鼓相当,一万条数据 500 ms左右。

         解释一下FMDB的伪批处理,因为FMDB默认每条插入操作都当做一次事务处理,所以单纯直接循环10000次插入操作,时间消耗非常之大,10000条数据约需三分钟,如果采用统一开启事务处理方式,FMDB自动取消每次插入的事务,处理速度大大加快,就是上述 10000条数据 500 ms左右。

         伪批处理(统一事务处理)代码如下:

    

//增加数据- (void)addFMDB {    [self.db beginTransaction];    BOOL isRollBack = NO;    @try {        //往表中循环插入100条数据        for (int i = 0; i < 50000 ; i++) {            //名称设置为J_mailbox            NSString *name = [NSString stringWithFormat:@"J_mailbox-%d",i];            //随机生成20岁~25岁之间的记录            NSInteger age = arc4random_uniform(5) + 20;                        //sql插入语句的拼接            NSString *resultStr = [NSString stringWithFormat:@"INSERT INTO t_test (NAME,AGE) VALUES('%@',%zd) ",name,age];                        //执行sql插入语句(调用FMDB对象方法)            BOOL success = [self.db executeUpdate:resultStr];            //判断是否添加成功//            if (success) {//                NSLog(@"添加数据成功!");//            }else{//                NSLog(@"添加数据失败!");//            }        }    } @catch (NSException *exception) {        isRollBack = YES;        [self.db rollback];    } @finally {        if (!isRollBack) {            [self.db commit];            NSLog(@"最终成功");        }    }}
        2) 对于查询操作,而且速度差不多,但对于批量删除操作,批量更新操作,由于CoreData需要先查询找到相应的实体对象然后再执行更新操作,效率低了很多。


3.完整FMDB和CoreData对比demo示例代码如下

            

#import "ViewController.h"#import <sqlite3.h>#import "FMDB.h"#import <CoreData/CoreData.h>@interface ViewController ()@property (strong,nonatomic) FMDatabase *db;@property (strong,nonatomic) NSManagedObjectContext *coreDataContext;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    [self initUI];    [self connectionDB];    [self initCoreData];}-(void)operetionClick:(UIButton *)btn{    CFAbsoluteTime startTime =CFAbsoluteTimeGetCurrent();        if (btn.tag < 4)    {        //fmdb        switch (btn.tag) {            case 0:            {                [self addFMDB];            }                break;            case 1:            {                [self deleteFMDB];            }                break;            case 2:            {                [self changeFMDB];            }                break;            case 3:            {                [self queryFMDB];            }                break;                            default:                break;        }    } else {        //core Data        switch (btn.tag) {            case 4:            {                [self addCoreData];            }                break;            case 5:            {                [self deleteCoreData];            }                break;            case 6:            {                            }                break;            case 7:            {                [self queryCoreData];            }                break;                            default:                break;        }    }    CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);        NSLog(@"Linked in %f ms", linkTime *1000.0);}- (void)initCoreData{    // 从应用程序包中加载模型文件    NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];    // 传入模型对象,初始化NSPersistentStoreCoordinator    NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];    // 构建SQLite数据库文件的路径    NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];    NSURL *url = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"person.data"]];    NSLog(@"%@",url);    // 添加持久化存储库,这里使用SQLite作为存储库    NSError *error = nil;    NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error];    if (store == nil) { // 直接抛异常        [NSException raise:@"添加数据库错误" format:@"%@", [error localizedDescription]];    }    // 初始化上下文,设置persistentStoreCoordinator属性    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];    context.persistentStoreCoordinator = psc;    self.coreDataContext = context;}- (void)addCoreData{    for (int i = 0; i < 10000; i++) {        NSManagedObject *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.coreDataContext];        // 设置Person的简单属性        [person setValue:[NSString stringWithFormat:@"zss%d",i] forKey:@"name"];        [person setValue:[NSNumber numberWithInt:27] forKey:@"age"];    }    // 利用上下文对象,将数据同步到持久化存储库    NSError *error = nil;    BOOL success = [self.coreDataContext save:&error];    if (!success) {        [NSException raise:@"访问数据库错误" format:@"%@", [error localizedDescription]];    } else {        NSLog(@"全部添加成功");    }}- (void)queryCoreData{    // 初始化一个查询请求    NSFetchRequest *request = [[NSFetchRequest alloc] init];    // 设置要查询的实体    request.entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.coreDataContext];    // 设置排序(按照age降序)//    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];//    request.sortDescriptors = [NSArray arrayWithObject:sort];    // 设置条件过滤(搜索name中包含字符串"Itcast-1"的记录,注意:设置条件过滤时,数据库SQL语句中的%要用*来代替,所以%Itcast-1%应该写成*Itcast-1*)//    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@", @"*Itcast-1*"];//    request.predicate = predicate;    // 执行请求    NSError *error = nil;    NSArray *objs = [self.coreDataContext executeFetchRequest:request error:&error];    if (error) {        [NSException raise:@"查询错误" format:@"%@", [error localizedDescription]];    }    // 遍历数据    for (NSManagedObject *obj in objs)    {        NSLog(@"name=%@", [obj valueForKey:@"name"]);    }}- (void)deleteCoreData{    // 初始化一个查询请求    NSFetchRequest *request = [[NSFetchRequest alloc] init];    // 设置要查询的实体    request.entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.coreDataContext];    NSError *error = nil;    NSArray *objs = [self.coreDataContext executeFetchRequest:request error:&error];    if (error) {        [NSException raise:@"查询错误" format:@"%@", [error localizedDescription]];    }    // 遍历数据    for (NSManagedObject *obj in objs)    {        // 传入需要删除的实体对象        [self.coreDataContext deleteObject:obj];    }    // 将结果同步到数据库    error = nil;    [self.coreDataContext save:&error];    if (error) {        [NSException raise:@"删除错误" format:@"%@", [error localizedDescription]];    } else {        NSLog(@"全部删除成功");    }}//连接数据库- (void)connectionDB{        //创建数据库路径    NSString *path  = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:@"data.sqlite"];    NSLog(@"%@",path);    FMDatabase *db = [FMDatabase databaseWithPath:path];    self.db = db;    BOOL success = [db open];    if (success) { //打开成功        NSLog(@"数据库创建成功!");        //创建表  执行一条sql语句  增删改 都是这样的  查询比较特殊        NSString *sqlStr = @"CREATE TABLE IF NOT EXISTS t_test (ID INTEGER PRIMARY KEY AUTOINCREMENT ,NAME TEXT ,AGE INTEGER );";        BOOL successT = [self.db executeUpdate:sqlStr];                if (successT) {            NSLog(@"创建表成功!");        }else{            NSLog(@"创建表失败!");        }                    }else{        NSLog(@"数据库创建失败!");    }        NSLog(@"%@",NSHomeDirectory());        //关闭数据库    //sqlite3_close(_db);}//增加数据- (void)addFMDB {    [self.db beginTransaction];    BOOL isRollBack = NO;    @try {        //往表中循环插入100条数据        for (int i = 0; i < 50000 ; i++) {            //名称设置为J_mailbox            NSString *name = [NSString stringWithFormat:@"J_mailbox-%d",i];            //随机生成20岁~25岁之间的记录            NSInteger age = arc4random_uniform(5) + 20;                        //sql插入语句的拼接            NSString *resultStr = [NSString stringWithFormat:@"INSERT INTO t_test (NAME,AGE) VALUES('%@',%zd) ",name,age];                        //执行sql插入语句(调用FMDB对象方法)            BOOL success = [self.db executeUpdate:resultStr];            //判断是否添加成功//            if (success) {//                NSLog(@"添加数据成功!");//            }else{//                NSLog(@"添加数据失败!");//            }        }    } @catch (NSException *exception) {        isRollBack = YES;        [self.db rollback];    } @finally {        if (!isRollBack) {            [self.db commit];            NSLog(@"最终成功");        }    }}//删除数据- (void)deleteFMDB {    //删除语句    NSString *sqlStr = @"DELETE FROM t_test WHERE AGE > 19 ;";    //执行sql删除语句(调用FMDB对象方法)    BOOL success = [self.db executeUpdate:sqlStr];        if (success) {        NSLog(@"删除数据成功!");    }else{        NSLog(@"删除数据失败!");    }}//修改数据- (void)changeFMDB{        //修改语句    NSString *sqlStr = @"UPDATE t_test SET AGE = 30 WHERE AGE > 19;";    //执行sql修改语句(调用FMDB对象方法)    BOOL success = [self.db executeUpdate:sqlStr];        if (success) {        NSLog(@"修改数据成功!");    }else{        NSLog(@"修改数据失败!");    }    }//查询数据- (void)queryFMDB {        //查询语句    NSString *sqlStr = @"SELECT NAME,AGE FROM t_test WHERE AGE > 19;";        //执行sql查询语句(调用FMDB对象方法)    FMResultSet *set =  [self.db executeQuery:sqlStr];        while ([set next]) { //等价于 == sqlite_Row        //NAME        NSString *name = [set stringForColumnIndex:0];        //AGE        NSInteger age = [set intForColumnIndex:1];                NSLog(@"NAME = %@ AGE = %ld",name,(long)age);    }    }- (void)initUI{    CGFloat x = 50,y = 50;    UILabel *fmdbLabel = [[UILabel alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    fmdbLabel.text = @"fmdb";    [fmdbLabel sizeToFit];    [self.view addSubview:fmdbLabel];        x -= 5;    y += 50;    UIButton *addBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    [addBtn setTitle:@"add" forState:UIControlStateNormal];    [addBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    addBtn.tag = 0;    [addBtn addTarget:self action:@selector(operetionClick:) forControlEvents:UIControlEventTouchUpInside];    [addBtn sizeToFit];    [self.view addSubview:addBtn];        y += 50;    UIButton *deleteBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    [deleteBtn setTitle:@"delete" forState:UIControlStateNormal];    [deleteBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    deleteBtn.tag = 1;    [deleteBtn addTarget:self action:@selector(operetionClick:) forControlEvents:UIControlEventTouchUpInside];    [deleteBtn sizeToFit];    [self.view addSubview:deleteBtn];        y += 50;    UIButton *changeBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    [changeBtn setTitle:@"change" forState:UIControlStateNormal];    [changeBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    changeBtn.tag = 2;    [changeBtn addTarget:self action:@selector(operetionClick:) forControlEvents:UIControlEventTouchUpInside];    [changeBtn sizeToFit];    [self.view addSubview:changeBtn];        y += 50;    UIButton *queryBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    [queryBtn setTitle:@"query" forState:UIControlStateNormal];    [queryBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    queryBtn.tag = 3;    [queryBtn addTarget:self action:@selector(operetionClick:) forControlEvents:UIControlEventTouchUpInside];    [queryBtn sizeToFit];    [self.view addSubview:queryBtn];        //Core Data        x = 200,y = 50;    UILabel *coreDataLabel = [[UILabel alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    coreDataLabel.text = @"coreData";    [coreDataLabel sizeToFit];    [self.view addSubview:coreDataLabel];        x -= 5;    y += 50;    UIButton *addBtn1 = [[UIButton alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    [addBtn1 setTitle:@"add" forState:UIControlStateNormal];    [addBtn1 setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    addBtn1.tag = 4;    [addBtn1 addTarget:self action:@selector(operetionClick:) forControlEvents:UIControlEventTouchUpInside];    [addBtn1 sizeToFit];    [self.view addSubview:addBtn1];        y += 50;    UIButton *deleteBtn1 = [[UIButton alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    [deleteBtn1 setTitle:@"delete" forState:UIControlStateNormal];    [deleteBtn1 setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    deleteBtn1.tag = 5;    [deleteBtn1 addTarget:self action:@selector(operetionClick:) forControlEvents:UIControlEventTouchUpInside];    [deleteBtn1 sizeToFit];    [self.view addSubview:deleteBtn1];        y += 50;    UIButton *changeBtn1 = [[UIButton alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    [changeBtn1 setTitle:@"change" forState:UIControlStateNormal];    [changeBtn1 setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    changeBtn1.tag = 6;    [changeBtn1 addTarget:self action:@selector(operetionClick:) forControlEvents:UIControlEventTouchUpInside];    [changeBtn1 sizeToFit];    [self.view addSubview:changeBtn1];        y += 50;    UIButton *queryBtn1 = [[UIButton alloc] initWithFrame:CGRectMake(x, y, 10, 10)];    [queryBtn1 setTitle:@"query" forState:UIControlStateNormal];    [queryBtn1 setTitleColor:[UIColor redColor] forState:UIControlStateNormal];    queryBtn1.tag = 7;    [queryBtn1 addTarget:self action:@selector(operetionClick:) forControlEvents:UIControlEventTouchUpInside];    [queryBtn1 sizeToFit];    [self.view addSubview:queryBtn1];}@end


原创粉丝点击