40

我有一个Person具有属性的实体personId(personId 是唯一的)

如何获取具有最大 personId 的人?

(我想获取人本身而不是财产的价值)

4

7 回答 7

68

您设置fetchLimitto1并按personId降序排序。例如:

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;
于 2012-05-01T13:11:24.980 回答
23

您需要使用带有 NSPredicate 的 NSFetchRequest 来指定您的查询...

改编自 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];
于 2012-05-01T13:20:02.217 回答
18

推荐的方法是使用Apple 推荐的方法NSExpression。我希望这会比使用排序便宜。如果您考虑一下,使用排序您将不得不对所有记录进行排序并保留最大的记录。使用表达式,您只需通读列表并将最大值保存在内存中。

这是我与 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;
}
于 2015-10-15T07:49:36.830 回答
8

上面使用 NSExpression 给出的答案是正确的。这是斯威夫特版本。

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
}

其中 moc 是一个 NSManagedObjectContext。

于 2017-03-07T09:58:24.207 回答
3

斯威夫特 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)
}
于 2017-09-12T13:23:55.620 回答
1

斯威夫特 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)")
}
于 2018-09-21T20:32:15.050 回答
0

除了 Ryan 的回答,在今天的 Swift 中,NSManagedObject'sexecute(_:)返回一个NSPersistentStoreResult对象,这需要一些额外的代码来检索该值:

// Cast `NSPersistentStoreResult` to `NSAsynchronousFetchResult<NSDictionary>`
let fetchResult = moc.execute(request) as! NSAsynchronousFetchResult<NSDictionary>

// Retrieve array of dictionary result
let dictsResult = fetchResult.finalResult

// Retrieve and cast the real result
let key = /* `expressionDescription.name` */
let result = dictsResult.first!.object(forKey: key) as! /* Your type, depending on `expressionDescription.expressionResultType` */

注意:上面使用强制不安全类型转换来简化代码,在实际情况下,您应该始终避免这种情况。

于 2020-08-18T11:07:36.917 回答