Ios 为什么我的NSFetchedResultsController加载所有行?

Ios 为什么我的NSFetchedResultsController加载所有行?,ios,objective-c,core-data,nsfetchedresultscontroller,nsfetchrequest,Ios,Objective C,Core Data,Nsfetchedresultscontroller,Nsfetchrequest,我有一个NSFetchedResultsController,用于在表视图中显示数据(22117行)。fetchBatchSize在fetchRequest上设置为20。它按预期工作:加载表视图时,只有20行完全填充。SQL语句: 2015-06-12 17:59:55.526 BoulderFinder[2228:1220755] CoreData: sql: SELECT 0, t0.Z_PK FROM ZBOULDER t0 ORDER BY t0.ZNORMALIZEDNAME 2015

我有一个NSFetchedResultsController,用于在表视图中显示数据(22117行)。fetchBatchSize在fetchRequest上设置为20。它按预期工作:加载表视图时,只有20行完全填充。SQL语句:

2015-06-12 17:59:55.526 BoulderFinder[2228:1220755] CoreData: sql: SELECT 0, t0.Z_PK FROM ZBOULDER t0 ORDER BY t0.ZNORMALIZEDNAME
2015-06-12 17:59:55.533 BoulderFinder[2228:1220755] CoreData: annotation: sql connection fetch time: 0.0070s
2015-06-12 17:59:55.534 BoulderFinder[2228:1220755] CoreData: annotation: total fetch execution time: 0.0075s for 22117 rows.
2015-06-12 17:59:55.534 BoulderFinder[2228:1220755]

2015-06-12 17:59:55.540 BoulderFinder[2228:1220755] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZBOULDERDESCRIPTION, t0.ZFIRSTCLIMBERFIRSTNAME, t0.ZFIRSTCLIMBERLASTNAME, t0.ZGRADE, t0.ZIMAGE, t0.ZLATITUDE, t0.ZLONGITUDE, t0.ZNAME, t0.ZNORMALIZEDAREANAME, t0.ZNORMALIZEDCIRCUITNAME, t0.ZNORMALIZEDGRADE, t0.ZNORMALIZEDNAME, t0.ZNUMBERINCIRCUIT, t0.ZAREA, t0.ZCIRCUIT FROM ZBOULDER t0 WHERE  t0.Z_PK IN  (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)  ORDER BY t0.ZNORMALIZEDNAME LIMIT 20
2015-06-12 17:59:55.541 BoulderFinder[2228:1220755] CoreData: annotation: sql connection fetch time: 0.0010s
2015-06-12 17:59:55.541 BoulderFinder[2228:1220755] CoreData: annotation: total fetch execution time: 0.0014s for 20 rows.
但是,我有另一个视图以不同的顺序显示相同的实体(只有少数实体通过谓词过滤)。在此视图中,我没有使用NSFetchedResultsController。如果我加载这个视图,其中在managedObjectContext中加载了大约59个对象,然后重新加载另一个表视图,那么NSFetchedResultsController现在将以20行为一批加载所有行(22117)。下面是SQL语句(仅前几条):

我找到的唯一解决方法是在设置NSFetchedResultsController之前调用resetContext

以下为相关代码:

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[BDBBoulder entityName]];
    NSSortDescriptor *normalizedNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"normalizedName" ascending:YES];
    fetchRequest.sortDescriptors = @[normalizedNameSortDescriptor];
    fetchRequest.fetchBatchSize = 20;
    // [self.fetchedResultsController.managedObjectContext reset];
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.boulderSearch.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    self.fetchedResultsController.delegate = nil;
    // Perform fetch
    NSError *error = nil;
    [self.fetchedResultsController performFetch:&error];
    if (error) {
        NSLog(@"Unable to perform fetch.");
        NSLog(@"%@, %@", error, error.localizedDescription);
    }
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    BDBBoulder *boulder = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text  = [NSString stringWithFormat:@"%@ / %@", boulder.normalizedName,boulder.grade];
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ / %@", boulder.normalizedCircuitName,boulder.normalizedAreaName];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSArray *sections = [self.fetchedResultsController sections];
    id<NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:section];

    return [sectionInfo numberOfObjects];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"allBouldersCell" forIndexPath:indexPath];
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}
-(void)viewDidLoad
{
[超级视图下载];
NSFetchRequest*fetchRequest=[NSFetchRequest fetchRequestWithEntityName:[BDBBoulder entityName]];
NSSortDescriptor*normalizedNameSortDescriptor=[NSSortDescriptor SortDescriptor WithKey:@“normalizedName”升序:是];
fetchRequest.sortDescriptors=@[normalizedNameSortDescriptor];
fetchRequest.fetchBatchSize=20;
//[self.fetchedResultsController.managedObjectContext重置];
self.fetchedResultsController=[[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:self.boulderSearch.managedObjectContext sectionNameKeyPath:nil缓存名称:nil];
self.fetchedResultsController.delegate=nil;
//执行提取
n错误*错误=nil;
[self.fetchedResultsController性能蚀刻:&错误];
如果(错误){
NSLog(@“无法执行获取”);
NSLog(@“%@,%@”,错误,错误。本地化描述);
}
}
-(void)configureCell:(UITableViewCell*)单元格atIndexPath:(NSIndexPath*)indexPath
{
BDBBoulder*boulder=[self.fetchedResultsController对象索引路径:indexPath];
cell.textLabel.text=[NSString stringWithFormat:@“%@/%@”,boulder.normalizedName,boulder.grade];
cell.detailTextLabel.text=[NSString stringWithFormat:@“%@/%@”,boulder.normalizedCircuitName,boulder.NormalizedAreName];
}
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节
{
NSArray*节=[self.fetchedResultsController节];
id sectionInfo=[sections objectAtIndex:section];
返回[sectionInfo numberOfObjects];
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell*单元格=[tableView dequeueReusableCellWithIdentifier:@“allBouldersCell”forIndexPath:indexPath];
[self-configureCell:cell-atIndexPath:indexPath];
返回单元;
}
我无法理解这种行为


编辑:

我已经用一个简化的应用程序再次执行了测试,以确定其行为。我有两个风投: -在第一个示例中,我获取fetchBatchSize为20的所有对象(22117),并访问结果的第一个元素 -在第二个示例中,我获取59个对象并修改它们的瞬态属性

fetchRequest.includesPendingChanges=是

如果加载第一个VC,则只有前20行完全加载:

2015-06-16 23:13:45.520 BoulderFinder[946:271012] CoreData: sql: SELECT 0, t0.Z_PK FROM ZBOULDER t0 
2015-06-16 23:13:45.528 BoulderFinder[946:271012] CoreData: annotation: sql connection fetch time: 0.0074s
2015-06-16 23:13:45.528 BoulderFinder[946:271012] CoreData: annotation: total fetch execution time: 0.0081s for 22117 rows.
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZBOULDERDESCRIPTION, t0.ZFIRSTCLIMBERFIRSTNAME, t0.ZFIRSTCLIMBERLASTNAME, t0.ZGRADE, t0.ZIMAGE, t0.ZLATITUDE, t0.ZLONGITUDE, t0.ZNAME, t0.ZNORMALIZEDAREANAME, t0.ZNORMALIZEDCIRCUITNAME, t0.ZNORMALIZEDGRADE, t0.ZNORMALIZEDNAME, t0.ZNUMBERINCIRCUIT, t0.ZAREA, t0.ZCIRCUIT FROM ZBOULDER t0 WHERE  t0.Z_PK IN  (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)   LIMIT 20
2015-06-16 23:13:45.532 BoulderFinder[946:271012] CoreData: annotation: sql connection fetch time: 0.0012s
2015-06-16 23:13:45.532 BoulderFinder[946:271012] CoreData: annotation: total fetch execution time: 0.0021s for 20 rows.
现在,如果我加载第二个VC,然后加载第一个VC,那么所有的行都是按20个批次加载的

但是,如果我在不修改transient属性的情况下执行相同的测试,那么只有前20行被完全加载

最后,如果fetchRequest.includesPendingChanges=NO

若要忽略挂起的更改,则它在所有情况下都会按预期工作

奇怪,但这就是它的工作原理。
谢谢。

您能否提供这两个视图控制器的详细信息以及如何加载/重新加载它们。我有一个导航控制器嵌入了一个“主视图”控制器,它是一个静态表视图。从这个视图中,我通过单击相应的单元格来选择要加载的视图控制器(“所有圆石”视图或“我周围”视图)。我正在使用故事板和“显示”分段加载视图控制器。谢谢。那么AllBoulders VC是一个具有FRC和22117行的VC,而在我周围是一个具有大约59个项目的VC?每次你访问它们时,它们是否都被初始化?是的,你是对的。是的,每次我访问它们时,它们都会被初始化(视图控制器是按照故事板中的指定间接实例化的)。抱歉,有这么多问题。我已经模拟了类似的东西,无法重现这个问题。您是否尝试过设置fetchRequest.includesPendingChanges=false?
2015-06-16 23:13:45.520 BoulderFinder[946:271012] CoreData: sql: SELECT 0, t0.Z_PK FROM ZBOULDER t0 
2015-06-16 23:13:45.528 BoulderFinder[946:271012] CoreData: annotation: sql connection fetch time: 0.0074s
2015-06-16 23:13:45.528 BoulderFinder[946:271012] CoreData: annotation: total fetch execution time: 0.0081s for 22117 rows.
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZBOULDERDESCRIPTION, t0.ZFIRSTCLIMBERFIRSTNAME, t0.ZFIRSTCLIMBERLASTNAME, t0.ZGRADE, t0.ZIMAGE, t0.ZLATITUDE, t0.ZLONGITUDE, t0.ZNAME, t0.ZNORMALIZEDAREANAME, t0.ZNORMALIZEDCIRCUITNAME, t0.ZNORMALIZEDGRADE, t0.ZNORMALIZEDNAME, t0.ZNUMBERINCIRCUIT, t0.ZAREA, t0.ZCIRCUIT FROM ZBOULDER t0 WHERE  t0.Z_PK IN  (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)   LIMIT 20
2015-06-16 23:13:45.532 BoulderFinder[946:271012] CoreData: annotation: sql connection fetch time: 0.0012s
2015-06-16 23:13:45.532 BoulderFinder[946:271012] CoreData: annotation: total fetch execution time: 0.0021s for 20 rows.