Core data UITableView将显示未使用空表激发的单元格

Core data UITableView将显示未使用空表激发的单元格,core-data,tableview,Core Data,Tableview,我使用coredata和一个fetchedResultsController来填充一个tableView,因为数据库非常大,有时当我在搜索栏中放置一个文本时,它需要4-5秒来显示对象,所以我启动一个微调器,然后在搜索结束时停止它。我使用委托方法willDisplayCell,如下所示,但当搜索返回0个对象时,微调器不会停止动画,因为willDisplayCell未被激发: - (BOOL)isFinishedLoadingTableView:(UITableView *)tableView in

我使用coredata和一个fetchedResultsController来填充一个tableView,因为数据库非常大,有时当我在搜索栏中放置一个文本时,它需要4-5秒来显示对象,所以我启动一个微调器,然后在搜索结束时停止它。我使用委托方法willDisplayCell,如下所示,但当搜索返回0个对象时,微调器不会停止动画,因为willDisplayCell未被激发:

- (BOOL)isFinishedLoadingTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath {
    NSArray *visibleRows = [tableView indexPathsForVisibleRows];   // did verify sorted ascending via logging
    NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
    // For tableviews with multiple sections this will be more complicated.
    BOOL isPreviousCallForPreviousCell = self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
    BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
    BOOL isFinishedLoadingTableView = isLastCell && ([tableView numberOfRowsInSection:0] == 1 || isPreviousCallForPreviousCell);
    self.previousDisplayedIndexPath = indexPath;
    return isFinishedLoadingTableView; }

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath
*)indexPath {
    BOOL isFinishedLoadingTableView = [self isFinishedLoadingTableView:tableView indexPath:indexPath];
    if (isFinishedLoadingTableView) {
        [activityIndicatorView stopAnimating];
    }
}
以下是财务汇报局:

(NSFetchedResultsController *)fetchedResultsController{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"CivicoEntity" inManagedObjectContext:context];
    [fetchRequest setEntity:entity];
    [fetchRequest setFetchBatchSize:20];

    NSMutableArray *finalSearchTextArray = [[NSMutableArray alloc]init];
    NSArray *tempSearchTextItems = [self.searchText componentsSeparatedByString:@" "];

    for (NSString *string in tempSearchTextItems){
        if([string length]>0)
            [finalSearchTextArray addObject:string];
    }

    if (self.searchText) {
        NSMutableArray *predicatesArray = [[NSMutableArray alloc]init];
        for (NSString *string in finalSearchTextArray) {
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"indirizzo CONTAINS[cd] %@ OR toponimo CONTAINS[cd] %@", string, string];
            [predicatesArray addObject:predicate];
        }
        NSPredicate * finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicatesArray];
        [fetchRequest setPredicate:finalPredicate];
    }

    NSSortDescriptor *sort_indirizzo = [[NSSortDescriptor alloc]
                              initWithKey:@"indirizzo" ascending:YES selector:@selector(caseInsensitiveCompare:)];
    NSSortDescriptor *sort_civico = [[NSSortDescriptor alloc]
                              initWithKey:@"civico" ascending:YES selector:@selector(localizedStandardCompare:)];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sort_indirizzo, sort_civico, nil]];


    NSFetchedResultsController *theFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                        managedObjectContext:context sectionNameKeyPath:nil
                                                   cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;
}
当tableview必须显示至少一行/单元格时,将调用willDisplayCell方法。这就是您的情况,您需要找到其他解决方案来停止微调器动画

尝试插入代码:

[activityIndicatorView stopAnimating];
在方法中:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
在这里面,检查:

if (numberOfRows_to_return == 0) {
    [activityIndicatorView stopAnimating];
}

我本来打算发表评论,但是没有足够的空间

如果我的理解是正确的,你有很多选择

你已经开发出了机制,但是还有其他一些方法来考虑做所需要的。请原谅,我不知道您在Objective-C方面的经验和技能水平

首先,我建议您阅读一下如何优化NSFetchedResultsController FRC。可能是,如果在FRC中设置批次大小,数据填充速度会更快,并且不需要微调器

我发现这两本书非常有用:Marcus S.Zarra于2013年1月出版的实用书架《核心数据,第二版,iOS、OS X和iCloud的数据存储和管理》,以及Michael Privat和Robert Warner出版的《使用核心数据的支持iOS持久化》,注仍在alpha中

其次,如何过滤数据进行搜索是很重要的。您可以在过滤器方法中包含完成块,该块将在方法完成后停止动画


因此,这确实是一个评论,但我没有房间,我想请你提供更多的信息。特别是有关FRC和搜索机制的信息会很有帮助。

我尝试过,但numberOfRowsInSection也会在获取结束前被调用,因此它返回0,然后在获取后返回实际值。它似乎是在检索数据之前和之后调用的。我用FRC代码更新了上面的问题。我使用的批处理大小为20,但DB非常大,有87.000条记录,大小为30MB。我使用dispatch\u异步调用开始抓取,在这里我执行performFetch,然后在主线程上执行另一个异步调用[mytableview reloadData]。即使我尝试计数fetchedResults对象,它也会在之前返回0,然后返回正确数量的已获取对象。这种行为总是预期willDisplayCell内的stopanimating调用,微调器在显示表格前几秒钟停止。我在performFetch之后放置了一个NSLog来计算获取的对象,我发现如果我在搜索栏中每次写入一个字符,它就会工作,但我必须等待表格加载,如果我一次写入更多字符,则在键入字符之间返回0,然后在最后返回正确的值,因此如果我在搜索栏中写入更多字符,微调器将立即停止动画,并且我不等待它们之间的结果…我想这取决于调度异步,因为当我键入一个字符时,它会发送一个线程来执行获取,在它结束之前,它会在我们考虑使用FRC中的错误或预取之前捕获一个字符和一个新的FET,您是否考虑过从FRC中破解搜索文本,要充当FRC FetchedObject的独立筛选器?在UISearchDisplayController委托方法searchDisplayController中对您的FetchedObject使用FilteredArrayingPredicate?searchDisplayController:shouldReloadTableForSearchString?中断搜索文本是什么意思?现在,我试图避免在键入时启动搜索,我强制用户按下搜索按钮,它工作正常,速度非常快。如果搜索在键入时启动,则为每个键入的字符分配一个异步线程,并使其在最后一个字符之前键入的每个字符返回0,或者您必须等待它在键入字符之间显示结果。