Core Data - How to fetch an entity with max value property

前端 未结 7 784
误落风尘
误落风尘 2020-12-05 02:06

I have a entity Person with a property personId (personId is unique)

How can I fetch the Person with the max personId?

(I want to f

相关标签:
7条回答
  • 2020-12-05 02:32

    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)
    }
    
    0 讨论(0)
  • 2020-12-05 02:39

    You set the fetchLimit to 1 and sort by personId in descending order. E.g.:

    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;
    
    0 讨论(0)
  • 2020-12-05 02:45

    The answer given above using NSExpression is correct. Here is the Swift version.

    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
    }
    

    where moc is a NSManagedObjectContext.

    0 讨论(0)
  • 2020-12-05 02:47

    The recommended way is to use Apple Recommended Method NSExpression. I would expect that this would be less expensive than using a sort.If you think about it, with a sort you would have to take all the records sort them and keep the maximum one. With an expression you would just have to read through the list and keep in memory the maximum.

    Here is an example I use with 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;
    }
    
    0 讨论(0)
  • 2020-12-05 02:48

    You need to use a NSFetchRequest with a NSPredicate to specify your query...

    Adapted from Apple's Predicate Progamming Guide :

    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];
    
    0 讨论(0)
  • 2020-12-05 02:51

    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)")
    }
    
    0 讨论(0)
提交回复
热议问题