4

In my app i've some records in core data and i want to fetch last 20 records in ascending order i.e.. if there is 30 records than i want to fetch records from 11 to 30 in ascending order -

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"Messages" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setFetchLimit:20];
    NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                              initWithKey:@"messageId" ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    NSPredicate *predicate = [NSPredicate predicateWithFormat: @"((userId == %@) && (frndId == %@) )",uid, fid];
    [fetchRequest setPredicate:predicate];

    NSError *error;
    NSArray* dataArray = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
    for (Messages* msg in dataArray) {
//code here
} 

but it gives me first 20 records in ascending order and if i change to

NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                                  initWithKey:@"messageId" ascending:NO];

then i got last 20 records but that was in ascending order?Any suggestion would be appreciated.

Blios
  • 719
  • 1
  • 16
  • 30

3 Answers3

9

cant you just set this offset?

//assume it fits an nsinteger
NSInteger count = [managedObjectContext countForFetchRequest:fetchRequest /*the one you have above but without limit */ error:&error];

NSUInteger size = 20;
count -= size;
[fetchRequest setFetchOffset:count>0?count:0];
[fetchRequest setFetchLimit:size];
NSArray* dataArray = [managedObjectContext executeFetchRequest:fetchRequest error:&error]
Daij-Djan
  • 49,552
  • 17
  • 113
  • 135
  • Note that if `count` is less than `size`, `count -= size` will result in a very large *positive* number... (+1 though) – Martin R Apr 05 '14 at 09:11
  • thanks yes... I forgot that it is unsigned... my whek is useless right now - ill edit it. thanks – Daij-Djan Apr 05 '14 at 09:23
3

NSFetchRequest does not provide a method for that. You have to fetch 20 records in descending order and then reverse the resulting data array:

dataArray = [[dataArray reverseObjectEnumerator] allObjects];

If this is for display in a table view, then instead of actually reversing the data array you could adapt the cellForRowAtIndexPath method to display the object

dataArray[dataArray.count - 1 - indexPath.row]

instead of

dataArray[indexPath.row]
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
3

you can use -

//your code as it is till this line but with 
//NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                              initWithKey:@"messageId" ascending:NO];
NSArray* dataArray = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];

    NSArray *sortedArray;
    sortedArray = [dataArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
        NSString *first = [(Messages*)a messageId];
        NSString *second = [(Messages*)b messageId];
        return [first compare:second];
    }];
    for (Messages* msg in sortedArray) {
//your code
}

Happy coding :P

Blios
  • 719
  • 1
  • 16
  • 30
Bharat
  • 2,987
  • 2
  • 32
  • 48