哇~~哈哈哈~开心~~
参考资料: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
完美解决我的需求。
网友评论