0

我在使用 NSFetchedResultsController 时遇到问题,我无法阻止它冻结 UI。初始提取发生得很快,但是当我触发任何错误时,它会在滚动表格视图时导致冻结。我只使用 8 个元素进行测试,我的后端使用 StackMob

这是我声明 NSFetchedResultsController 的地方

- (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"]);
});

但随后需要很长时间 20 秒左右

4

1 回答 1

1

在您的获取请求上设置一个fetchBatchSize等于您的表格在屏幕上的行数的两倍左右。这将不必加载整个数据集。另请参阅NSFetchedResultsController有关cacheName.

顺便说一句,你[[self.appDelegate coreDataStore] contextForCurrentThread]看起来很可疑。所有这些 UI 代码都将在主线程上执行,因此几乎可以肯定没有必要让另一个对象生成每个线程的 MOC。

您的 GCD 代码不正确,因为您现在有主 UI 线程和您的 GCDcoreDataThread都在与相同的通信NSFetchedResultsController,因此两个线程与同一个 MOC 通信。

如果您对 Core Data 的性能感到困惑,那么打开 SQL 日志记录是值得的。

-com.apple.CoreData.SQLDebug 1

作为命令行参数,通过方案编辑器启用。

于 2013-03-27T00:23:39.217 回答