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

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


发布了18 篇原创文章 · 获赞 1 · 访问量 7678

猜你喜欢

转载自blog.csdn.net/leitingdulante/article/details/72822103