Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 核心数据请求的分页结果_Objective C_Ios_Core Data - Fatal编程技术网

Objective c 核心数据请求的分页结果

Objective c 核心数据请求的分页结果,objective-c,ios,core-data,Objective C,Ios,Core Data,我有一个相对简单的核心数据sqlite数据库。我试图从数据库中一页一页地获取结果 NSFetchRequest* request = [[[NSFetchRequest alloc] init] autorelease]; [request setEntity:[...]]; [request setPredicate:[NSPredicate predicateWithFormat:@"flaggedTime != nil"]]; NSSortDescri

我有一个相对简单的核心数据sqlite数据库。我试图从数据库中一页一页地获取结果


    NSFetchRequest* request = [[[NSFetchRequest alloc] init] autorelease];
    [request setEntity:[...]];

    [request setPredicate:[NSPredicate predicateWithFormat:@"flaggedTime != nil"]];

    NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"flaggedTime" ascending:NO];
    [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

    [request setFetchLimit:pageSize];
    [request setFetchOffset:((pageIndex - 1) * pageSize)];    

    NSArray* results = [self.context executeFetchRequest:request error:NULL];
pageSize为30,测试数据的pageIndex为1、2、3或4(数据库中大约有80个项目,因此pageIndex=4不应返回任何项目)。 谓词和排序工作正常,结果成功返回。取数限制也很好。不会返回任何错误

问题:我总是从第一页获得结果,就好像没有设置fetchOffset一样。我试图删除谓词和排序,但没有成功。 我唯一能使fetchOffset工作的情况是使用小于30的值。当然,这对于分页来说毫无意义

有人知道为什么吗?对于每一个答案,我都会非常感激

更新:我说的是iOS。在4.2和5.0上测试

更新2:简化问题


    NSFetchRequest* request = [[[NSFetchRequest alloc] init] autorelease];
    [request setEntity:[...];

    NSError* error = nil;

    NSManagedObjectContext* context = [...];

    NSUInteger count = [context countForFetchRequest:request error:&error];
    assert(error == nil);

    NSLog(@"Total count: %u", count);

    request.fetchOffset = 0;    
    request.fetchLimit = 30;

    NSLog(@"Fetch offset: %u, limit: %u", request.fetchOffset, request.fetchLimit);

    NSArray* page1 = [context executeFetchRequest:request error:&error];
    assert(error == nil);

    NSLog(@"Page 1 count: %u", page1.count);

    request.fetchOffset = 30;    
    request.fetchLimit = 30;

    NSLog(@"Fetch offset: %u, limit: %u", request.fetchOffset, request.fetchLimit);

    NSArray* page2 = [context executeFetchRequest:request error:&error];
    assert(error == nil);

    NSLog(@"Page 2 count: %u", page2.count);
给出:

Total count: 34 Fetch offset: 0, limit: 30 Page 1 count: 30 Fetch offset: 30, limit: 30 Page 2 count: 30 (ERROR: should give 4) 总数:34 获取偏移量:0,限制:30 第1页计数:30 取回偏移量:30,限制:30 第2页计数:30(错误:应给出4)
我刚刚创建了一个演示项目,试图以最简单的形式重新创建您的场景。我创建了一个空白项目,添加了34个对象,然后用上面列出的代码查询它。下面是一个例子:

CDAppDelegate * delegate = (CDAppDelegate*)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext * context = [delegate managedObjectContext];
for(int i = 0; i < 34;i++){
    CDObject * object = [NSEntityDescription insertNewObjectForEntityForName:@"CDObject"
                                                      inManagedObjectContext:context];
    [object setValue:i];
}
[delegate saveContext];

NSFetchRequest* request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:@"CDObject"
                               inManagedObjectContext:context]];

 NSError* error = nil;

 NSUInteger count = [context countForFetchRequest:request error:&error];
 assert(error == nil);

 NSLog(@"Total count: %u", count);

 request.fetchOffset = 0;    
 request.fetchLimit = 30;

 NSLog(@"Fetch offset: %u, limit: %u", request.fetchOffset, request.fetchLimit);

 NSArray* page1 = [context executeFetchRequest:request error:&error];
 assert(error == nil);

 NSLog(@"Page 1 count: %u", page1.count);

 request.fetchOffset = 30;    
 request.fetchLimit = 30;

 NSLog(@"Fetch offset: %u, limit: %u", request.fetchOffset, request.fetchLimit);

 NSArray* page2 = [context executeFetchRequest:request error:&error];
 assert(error == nil);

 NSLog(@"Page 2 count: %u", page2.count);

[request release];

使用您的代码,我可以让它正常运行。这是在模拟器上运行iOS5.0时完成的。在我看来,您的代码是正确的,因为您正在尝试完成,所以在针对未保存的上下文运行提取请求时,
NSFetchRequest
pageOffset
属性(有时?)会被忽略。请注意,在code by OP上下文中是如何从不保存的,而在@kcharwood所提供答案的代码片段中,它实际上是保存的。以下是一个例子:

- (void) printArrayOfTestEntities:(NSArray *)array{
    NSMutableString * s = [NSMutableString new];
    NSArray * numbers = [array valueForKey:@"someField"];
    for (NSNumber * number in numbers){
        [s appendString:[NSString stringWithFormat:@"%d ", [number intValue]]];
    }

    NSLog(@"fetched objects: %@ \rcount: %d", s, array.count);
}

/* example itself */

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[context setPersistentStoreCoordinator:persistentStoreCoordinator];

for(int i = 0; i < 34;i++){
    NSManagedObject * object = [NSEntityDescription insertNewObjectForEntityForName:@"TestEntity"
                                                      inManagedObjectContext:context];
    [object setValue:@(i) forKey:@"someField"];
}

NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"TestEntity"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"someField" ascending:YES]];
request.fetchLimit = 30;

NSArray * result = [context executeFetchRequest:request error:nil];
[self printArrayOfTestEntities:result];

request.fetchOffset = 30;
result = [context executeFetchRequest:request error:nil];
[self printArrayOfTestEntities:result];

[context save:&error];

request.fetchOffset = 0;
result = [context executeFetchRequest:request error:nil];
[self printArrayOfTestEntities:result];

request.fetchOffset = 30;
result = [context executeFetchRequest:request error:nil];
[self printArrayOfTestEntities:result];

核心数据内置分页功能,非常简单,只需在获取请求上设置fetchBatchSize。当将所有对象的fetch just查询设置为faults时,基本上只是一个指针及其行索引,它是一种称为批处理faulting数组的特殊数组的最小内存。我认为这在大多数情况下都很好,尽管我还没有研究过它对大量行使用多少内存。然后,当您在访问故障记录的属性时循环此数组时,它会在数据库中查询该记录和下一个记录,直到您为批量大小设置的数量为止。这允许您像正常情况一样逐个循环结果,但在后台它会批量加载数据。从iOS 9.2开始,最小批量大小为4,因此没有任何一点设置低于该值的数字

我们可以看看设置页面大小和页面索引的代码吗?此外,显示结果的代码?与此无关。问题就在这里。我知道你不相信我,你希望在其他地方找到一个简单的解决方案,但是方法中的参数就是我上面写的。但我很好奇-你真的有一个同时使用fetchLimit和fetchOffset的工作代码吗?我有一个使用fetchLimit、fetchOffset和SortDescriptor的工作代码-就像你一样。我的代码运行良好。打开数据库或请求设置时会有差异吗?我知道文档中的状态是“在嵌套请求(如子查询)中忽略偏移量”。但我认为我的请求非常简单。@Sulthan您可能必须共享momd文件以帮助重现错误。我认为OP的问题是概念上与“页面”和“分页”混淆。在这个隐含的数据模型或显式代码中,没有任何内在的页面。他没有像编程中通常使用的那样“翻页”任何东西,仍然试图在新创建的模型上重现这个问题。请耐心一点。这个问题早该提了,我相信这就是当时的实际问题。未保存的上下文。由于这个答案,我可以在我的程序中找到一个错误。我只想补充一点,获取的对象是未保存的对象。我不敢相信苹果没有记录这个问题。需要注意的是,这个例子之所以有效,是因为你使用的上下文是基础上下文,而不是它的子上下文。在子上下文中运行相同种类的场景仍然会产生不好的结果,即使保存到将更改保存到持久存储中。这是因为fetchOffset属性依赖sqlite和磁盘上的db来运行。这确实会在objective-c中引起警告,但它们只会返回坏结果。
- (void) printArrayOfTestEntities:(NSArray *)array{
    NSMutableString * s = [NSMutableString new];
    NSArray * numbers = [array valueForKey:@"someField"];
    for (NSNumber * number in numbers){
        [s appendString:[NSString stringWithFormat:@"%d ", [number intValue]]];
    }

    NSLog(@"fetched objects: %@ \rcount: %d", s, array.count);
}

/* example itself */

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[context setPersistentStoreCoordinator:persistentStoreCoordinator];

for(int i = 0; i < 34;i++){
    NSManagedObject * object = [NSEntityDescription insertNewObjectForEntityForName:@"TestEntity"
                                                      inManagedObjectContext:context];
    [object setValue:@(i) forKey:@"someField"];
}

NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"TestEntity"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"someField" ascending:YES]];
request.fetchLimit = 30;

NSArray * result = [context executeFetchRequest:request error:nil];
[self printArrayOfTestEntities:result];

request.fetchOffset = 30;
result = [context executeFetchRequest:request error:nil];
[self printArrayOfTestEntities:result];

[context save:&error];

request.fetchOffset = 0;
result = [context executeFetchRequest:request error:nil];
[self printArrayOfTestEntities:result];

request.fetchOffset = 30;
result = [context executeFetchRequest:request error:nil];
[self printArrayOfTestEntities:result];
2014-03-01 11:30:06.986 coredatatest[19771:70b] fetched objects: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29  
count: 30
2014-03-01 11:30:06.990 coredatatest[19771:70b] fetched objects: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29  
count: 30
2014-03-01 11:30:06.995 coredatatest[19771:70b] fetched objects: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29  
count: 30
2014-03-01 11:30:06.997 coredatatest[19771:70b] fetched objects: 30 31 32 33   
count: 4