web-dev-qa-db-fra.com

Core Data - Comment récupérer une entité avec la propriété max value

J'ai une entité Person avec une propriété personId (personId est unique)

Comment puis-je récupérer la personne avec le max personId?

(Je veux aller chercher la personne elle-même et non la valeur de la propriété)

39
Eyal

Vous définissez fetchLimit sur 1 et trier par personId dans l'ordre décroissant. Par exemple.:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Person"];

fetchRequest.fetchLimit = 1;
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"personId" ascending:NO]];

NSError *error = nil;

id person = [managedObjectContext executeFetchRequest:fetchRequest error:&error].firstObject;
68
hypercrypt

Vous devez utiliser un NSFetchRequest avec un NSPredicate pour spécifier votre requête ...

Adapté du guide de programmation des prédicats d'Apple:

NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person"
    inManagedObjectContext:managedObjectContext];
[request setEntity:entity];

request.predicate = [NSPredicate predicateWithFormat:@"personId==max(personId)"];
request.sortDescriptors = [NSArray array];

NSError *error = nil;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
23
Uilleann

La méthode recommandée consiste à utiliser méthode recommandée par Apple NSExpression. Je m'attendrais à ce que ce soit moins cher que d'utiliser un tri.Si vous y réfléchissez, avec un tri, vous devrez prendre tous les enregistrements pour les trier et en conserver le maximum. Avec une expression, il suffit de lire la liste et de garder en mémoire le maximum.

Voici un exemple que j'utilise avec NSDate

- (NSDate *)lastSync:(PHAssetMediaType)mediaType {
    NSEntityDescription *entity = [NSEntityDescription  entityForName:kMediaItemEntity inManagedObjectContext:self.managedObjectContext];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    fetchRequest.entity = entity;
    fetchRequest.resultType = NSDictionaryResultType;

    NSMutableArray *predicates = [NSMutableArray array];
    [predicates addObject:[NSPredicate predicateWithFormat:@"%K=%d", kMediaType,mediaType]];
    [predicates addObject:[NSPredicate predicateWithFormat:@"%K=%d", kMediaProviderType,self.mediaProviderType]];
    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates: predicates];
    fetchRequest.predicate = predicate;

    // Create an expression for the key path.

    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:kSyncTime];
    // Create an expression to represent the function you want to apply

    NSExpression *maxExpression = [NSExpression expressionForFunction:@"max:"
                                                            arguments:@[keyPathExpression]];

    // Create an expression description using the maxExpression and returning a date.
    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
    [expressionDescription setName:@"maxDate"];
    [expressionDescription setExpression:maxExpression];
    [expressionDescription setExpressionResultType:NSDateAttributeType];

    // Set the request's properties to fetch just the property represented by the expressions.
    fetchRequest.propertiesToFetch = @[expressionDescription] ; // @[kSyncTime];

    NSError *fetchError = nil;
    id requestedValue = nil;

    // fetch stored media
    NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];
    if (fetchError || results == nil || results.count == 0) {
        return [NSDate dateWithTimeIntervalSince1970:0];
    }
    requestedValue = [[results objectAtIndex:0] valueForKey:@"maxDate"];
    if (![requestedValue isKindOfClass:[NSDate class]]) {
        return [NSDate dateWithTimeIntervalSince1970:0];
    }
    DDLogDebug(@"sync date %@",requestedValue);
    return (NSDate *)requestedValue;
}
17
Ryan Heitner

La réponse donnée ci-dessus en utilisant NSExpression est correcte. Voici la version Swift.

private func getLastSyncTimestamp() -> Int64? {

let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest()
request.entity = NSEntityDescription.entity(forEntityName: "EntityName", in: self.moc)
request.resultType = NSFetchRequestResultType.dictionaryResultType

let keypathExpression = NSExpression(forKeyPath: "timestamp")
let maxExpression = NSExpression(forFunction: "max:", arguments: [keypathExpression])

let key = "maxTimestamp"

let expressionDescription = NSExpressionDescription()
expressionDescription.name = key
expressionDescription.expression = maxExpression
expressionDescription.expressionResultType = .integer64AttributeType

request.propertiesToFetch = [expressionDescription]

var maxTimestamp: Int64? = nil

do {

    if let result = try self.moc.fetch(request) as? [[String: Int64]], let dict = result.first {
       maxTimestamp = dict[key]
    }

} catch {
    assertionFailure("Failed to fetch max timestamp with error = \(error)")
    return nil
}

return maxTimestamp
}

où moc est un NSManagedObjectContext.

7
jarora

Swift 3

let request:NSFetchRequest = Person.fetchRequest()

let sortDescriptor1 = NSSortDescriptor(key: "personId", ascending: false)

request.sortDescriptors = [sortDescriptor1]

request.fetchLimit = 1

do {
    let persons = try context.fetch(request)
    return persons.first?.personId
} catch {
    print(error.localizedDescription)
}
2
Rajat Jain

Swift 4

let request: NSFetchRequest<Person> = Person.fetchRequest()
request.fetchLimit = 1

let predicate = NSPredicate(format: "personId ==max(personId)")
request.predicate = predicate

var maxValue: Int64? = nil
do {
    let result = try self.context.fetch(request).first
    maxValue = result?.personId
} catch {
    print("Unresolved error in retrieving max personId value \(error)")
}
1
hamada147