iOS FMDB写入导致UI刷新卡顿

哇~~哈哈哈~开心~~

参考资料:https://www.jianshu.com/p/7bf051d524ae

首先描述一个问题,app登录后异步线程完成3000+条数据的写入数据库。首页UI刷新阻塞。分析原因:异步线程占用资源过多,抢占了主线程资源。

解决方案:

    dispatch_queue_t workConcurrentQueue = dispatch_queue_create("workConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t serialQueue= dispatch_queue_create("serialQueue",DISPATCH_QUEUE_SERIAL);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
    
    for (NSInteger i = 0; i < self.orginTree.count; i++) {
        
        dispatch_async(serialQueue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            dispatch_async(workConcurrentQueue, ^{
                OrginiztionModel *model = self.orginTree[i];
                NSString *sql = [NSString stringWithFormat:@"<#sq 语句#>",@"<#参数拼接#>"];
                
                BOOL isSuccess = [[AcficDBManager shareDBManager] updateRequestInPublicDB:sql];
                if(!isSuccess){
                    NSLog(@"插入数据失败:\n%@",sql);
                }

                dispatch_semaphore_signal(semaphore);
            });
        });
    }

内容更新,上述方式可以解决数据库写入,卡塞主线程。依然存在问题:
1.消耗时间过长。
2.在写入过程中,读取数据不全。
so~~~ 寻找解决方案。利用FMDB的事务解决。 即在数据写入前做个一全部数据的快照,然后一次性全部写入。
上代码:

#pragma mark -- 数据库批量更新
- (BOOL)acficUpdateOrgTree:(NSArray *)sqls {
    if (sqls == nil) {
        NSLog(@"执行sql集合为nil");
        return NO;
    }
    if(sqls.count == 0){
        NSLog(@"执行sql集合为空");
        return NO;
    }
    __block BOOL isSuccess = YES;
    //获取沙河下的数据库
    NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    self.publicFullPath = [NSString stringWithFormat:@"%@/%@.db",rootPath, Acfic_PublicDB];
    
    FMDatabase *base = [[FMDatabase alloc]initWithPath: self.publicFullPath];
    if(base == nil){
        NSLog(@"获取数据库失败");
        return NO;
    }
    [base open];
    @try {
        if([base beginTransaction]){
            for (NSString *sql in sqls) {
                [base executeStatements:sql];
            }
        }else{
            isSuccess = NO;
            NSLog(@"事务开启失败");
        }
        
    } @catch (NSException *exception) {
        isSuccess = NO;
        [base rollback];
        NSLog(@"数据库写入失败原因:%@",exception);
    } @finally {
        if(isSuccess){
            //事务提交
            if([base commit]){
                NSLog(@"事务结束,插入数据完成");
            }else{
                NSLog(@"事务commit失败");
                isSuccess = NO;
            }
        }
    }
    [base close];
    return isSuccess;
}

  • PS:FMDB版本2.6.2

完美解决我的需求。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一.资源抢夺 2> 资源抢夺解决方案 @sychronized{ } dispatch_barrier_async...
    蓝心儿的蓝色之旅阅读 5,183评论 0 4
  • 其实,从小到大总是种郁郁寡欢的性格,却总是强撑着展现自己的坚强。当心中沉积了太多思绪时,便把那些无言倾注给...
    逆时光_cf91阅读 1,215评论 0 1
  • 我却确不是个令她讨喜的女儿。 我的脑子里常常装满一些稀奇古怪的东西。 我的童年从来没有经历过父母的玩笑,诸如你是我...
    沛慈阅读 937评论 0 0
  • 原本以为,我的心已经是波澜不惊。 却在听到你的声音的那一刻已经风起云涌……
    LeAnn_He阅读 1,183评论 0 0
  • 概述 这是iOS项目中都会有的main.h文件,它底层的伪代码大概如此: RunLoop,运行循环,在程序运行过程...
    朝夕向背阅读 1,612评论 0 0