Duck
Duck

Reputation: 35953

How do I get the last record of a Core Data database?

I have a core data entity called images that has just 2 fields:

imageName = NSString
timeStamp = NSNumber

I am trying to simulate a kind of stack LIFO (last in first out). Inserting a new entry is easy but what about reading the last entry added to the entity?

All images are added with a timestamp, obtained by using

time_t unixTime = (time_t) [[NSDate date] timeIntervalSince1970];

an integer that is equal to the number of seconds since 1970

so, how do I retrieve the last inserted record of a core data (= the record that has the biggest timestamp number)???

thanks

Upvotes: 4

Views: 15238

Answers (3)

oscar castellon
oscar castellon

Reputation: 3138

In Swift 4, declare:

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = [Entity]()


func getLastRecord() {
     let entityCount = (entity.count - 1)
     let lastRecord = entity[entityCount] // This is the las attribute of your core data entity
     print(lastRecord)
    }

Upvotes: -1

Jeremy Fox
Jeremy Fox

Reputation: 2668

I have tried using the method that Chris Doble mentioned and found it to be very slow, especially if there are lot of records that would need to be pulled and checked against the timeStamp. If you want to speed things up, I am now setting an attribute called isMostRecent on my ManagedObject's that I may ever want to get the most recent from. When a new record is to be stored I just grab the most recent record that has this attribute set to YES and change it to NO then set the new record that is being stored to YES. The next time I need to grab to most recent record all I have to do is this...

+ (Photo*)latestPhotoForMOC:(NSManagedObjectContext*)context {
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:kCoreDataEntityNamePhoto
                                          inManagedObjectContext:context];
    [request setEntity:entity];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isMostRecent == %@", [NSNumber numberWithBool:YES]];
    [request setPredicate:predicate];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"isMostRecent" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];

    NSError *error = nil;
    NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];

    Photo* photo = nil;
    if (mutableFetchResults && mutableFetchResults.count > 0) {
        photo = [mutableFetchResults objectAtIndex:0];
    }

    return photo;
}

I have found this to be much faster. Yes, it requires a little more on your part to ensure it is used properly and that you don't ever end up with more than one record marked as isMostRecent but for me this was the best option.

Hope this helps someone else too.

Upvotes: 0

user94896
user94896

Reputation:

Perform a fetch request, sorting the results by timeStamp.

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

// Results should be in descending order of timeStamp.
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"timeStamp" ascending:NO];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

NSArray *results = [managedObjectContext executeFetchRequest:request error:NULL];
Entity *latestEntity = [results objectAtIndex:0];

You might also want to restrict the number of results using NSFetchRequest's setFetchLimit:.

Upvotes: 25

Related Questions