UI 在执行 NSBatchDeleteRequest 时冻结
Posted
技术标签:
【中文标题】UI 在执行 NSBatchDeleteRequest 时冻结【英文标题】:UI freezes on executing NSBatchDeleteRequest 【发布时间】:2017-11-27 17:37:22 【问题描述】:NSFetchRequest *request = [Report fetchRequest];
request.predicate = [NSPredicate predicateWithFormat: @"reportId IN %@",self.selectedRowsInEditMode];
NSBatchDeleteRequest *deleteDetailsRequest = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
deleteDetailsRequest.resultType = NSBatchDeleteResultTypeStatusOnly;
[self.managedObjectContext executeRequest:deleteDetailsRequest error:&errorExecuteRequest];
if (!errorExecuteRequest)
NSError *deleteSaveError;
BOOL saveSuccessful = [self.managedObjectContext save:&deleteSaveError];
[self.tableView removeLoadingActivityView];
这是我试图一次删除多个报告托管对象的代码,但是当调用 executeRequest 时,UI 会冻结一段时间然后删除。但是 NSBatchDeleteRequest 在删除方面应该非常快。我尝试了多次修改以使其正常工作,但没有成功。 我不确定我在这里做错了什么。所以任何人都可以建议让它在没有 UI 故障的情况下工作。
【问题讨论】:
能否启用 SQLDebug 并发布控制台输出。它应该显示有关正在处理以完成批量删除的 SQL 请求的一些详细信息。 您是否知道您的数据库有多大以及您要删除的对象大致有多少?您的批量删除请求也在主线程上执行吗? (我想是的,如果它冻结了 UI) @frankodwyer 我之前在主队列上有代码,然后我把它移到了一个单独的后台队列。这样就解决了,但我担心 NSBatchDeleteRequest 需要一些时间来删除甚至删除单个实体的请求。该实体有一个具有无效规则的关系对象。即使我有一个单一的关系 obj 那么也需要时间。 @pbasdf 无法发布数据库的控制台日志,因为我无法共享数据信息。 @pbasdf 我只能说我在这里使用的实体对象有几个关系。但即使我在其中一个关系中只有一个关系对象,也需要时间。但我想大致了解 NSBathcDeleteRequest 的行为如何? 【参考方案1】:希望下面的代码对你有所帮助!!
我最终添加了以下内容来处理批量删除后的上下文。
[self.managedObjectContext refreshAllObjects];
// Initialize Fetch Request
NSFetchRequest *fetchRequest = [Report fetchRequest];
// Add Sort Descriptors
fetchRequest.predicate = [NSPredicate predicateWithFormat: @"reportId IN %@",self.selectedRowsInEditMode];
// Initialize Asynchronous Fetch Request
NSAsynchronousFetchRequest *asynchronousFetchRequest = [[NSAsynchronousFetchRequest alloc] initWithFetchRequest:fetchRequest completionBlock:^(NSAsynchronousFetchResult *result)
dispatch_async(dispatch_get_main_queue(), ^
// Process Asynchronous Fetch Result
[weakSelf processAsynchronousFetchResult:result];
);
];
// Execute Asynchronous Fetch Request
[self.managedObjectContext performBlock:^
// Execute Asynchronous Fetch Request
NSError *asynchronousFetchRequestError = nil;
NSAsynchronousFetchResult *asynchronousFetchResult = (NSAsynchronousFetchResult *)[weakSelf.managedObjectContext executeRequest:asynchronousFetchRequest error:&asynchronousFetchRequestError];
if (asynchronousFetchRequestError)
NSLog(@"Unable to execute asynchronous fetch result.");
NSLog(@"%@, %@", asynchronousFetchRequestError, asynchronousFetchRequestError.localizedDescription);
];
或者使用下面你使用全局队列在后台运行东西和主队列来更新 UI
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
//Background Thread
dispatch_async(dispatch_get_main_queue(), ^(void)
//Run UI Updates
);
);
【讨论】:
感谢您提供的信息,但我想要一个解决方案或建议,为什么批量删除需要这么多时间。想知道我是否在批量删除花费这么多时间时做错了什么。异步获取请求将是最后一种方法,并为用户提供有关删除正在进行中的指示符。但想知道是否有任何方法可以防止 BatchDeleteRequest 花费这么多时间 使用这一行代码 [self.managedObjectContext refreshAllObjects];希望能帮到你! 在执行 batchdeleterequest 之前刷新? 是在执行批量删除请求之前使用 您提到“我最终添加了以下内容以处理批量删除后的上下文。”那么你的意思是在调用 execute:(BatchRequest) 之后添加上面提到的代码吗?如果是这样,那么我在调用 execute:(BatchRequest) 后不会遇到问题,但问题是 execute:(BatchRequest) 本身需要很多时间。【参考方案2】:您可以创建一个异步获取请求,同步可以冻结 UI。此链接Asynchronous Fetch Request 是 Objective C 中的一个教程,它解释了如何。
【讨论】:
以上是关于UI 在执行 NSBatchDeleteRequest 时冻结的主要内容,如果未能解决你的问题,请参考以下文章
UI 在执行 NSBatchDeleteRequest 时冻结