Objective c NSFetchedResultsController冻结UI
我在使用NSFetchedResultsController时遇到问题,无法阻止它冻结UI。初始获取发生得很快,但当我触发任何错误时,它会在滚动表视图时导致冻结。我只使用8个元素进行测试,我的后端使用StackMob 这里是我声明NSFetchedResultsController的地方Objective c NSFetchedResultsController冻结UI,objective-c,core-data,uitableview,nsfetchedresultscontroller,Objective C,Core Data,Uitableview,Nsfetchedresultscontroller,我在使用NSFetchedResultsController时遇到问题,无法阻止它冻结UI。初始获取发生得很快,但当我触发任何错误时,它会在滚动表视图时导致冻结。我只使用8个元素进行测试,我的后端使用StackMob 这里是我声明NSFetchedResultsController的地方 - (NSFetchedResultsController *)fetchedResultsController { if (_fetchedResultsController != nil) {
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Post"
inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"createddate" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:_managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
_fetchedResultsController = theFetchedResultsController;
return _fetchedResultsController;
}
以下是我的viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
UIColor* backgroundImage = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:BACKGROUND_IMAGE_TAN]];
[[self view] setBackgroundColor:backgroundImage];
[[self tableView] setSeparatorStyle:UITableViewCellSeparatorStyleNone];
_managedObjectContext = [[self.appDelegate coreDataStore] contextForCurrentThread];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort(); // Fail
}
}
这是我的cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"CCCell";
CCCell *cell = (CCCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CCCell" owner:nil options:nil];
cell = [topLevelObjects objectAtIndex:0];
[cell setDelegate:self];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
Post* post = (Post*)[_fetchedResultsController objectAtIndexPath:indexPath];
//
//IF I UNCOMMENT THIS LINE IT LOCKS THE UI
//
//NSLog(@"%@", [post valueForKey:@"price"]);
return cell;
}
如果我取消注释指定的行,会导致非常慢的滚动
我试着用这样的电话来包围这个电话
dispatch_queue_t coreDataThread = dispatch_queue_create("com.YourApp.YourThreadName", DISPATCH_QUEUE_SERIAL);
dispatch_async(coreDataThread, ^{
Post* post = (Post*)[_fetchedResultsController objectAtIndexPath:indexPath];
NSLog(@"%@", [post valueForKey:@"price"]);
});
但是,在获取请求上设置一个
fetchBatchSize
,大约等于屏幕上表的行数的两倍,这需要20秒左右的时间。这样就不用加载整个数据集了。另请参见NSFetchedResultsController
上的cacheName
文档
顺便说一下,您的[[self.appDelegate coreDataStore]contextForCurrentThread]
看起来可疑。所有这些UI代码都将在主线程上执行,因此要求另一个对象生成每个线程的MOC几乎肯定是没有必要的
您的GCD代码不正确,因为您现在有主UI线程和GCDcoreDataThread
与同一NSFetchedResultsController
对话,因此两个线程与同一MOC对话
如果您曾经对核心数据性能感到困惑,那么打开SQL日志记录是值得的
-com.apple.CoreData.SQLDebug 1
作为命令行参数,通过方案编辑器启用