核心数据 – 如何获取具有最大值属性的实体
我有一个实体Person
与财产personId
(personId是唯一的)
我怎样才能获取最大personId的人?
(我想把这个人本身取而不是财产的价值)
您将fetchLimit
设置为1
,并按降序排列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;
您需要使用NSFetchRequest与NSPredicate来指定您的查询…
改编自苹果公司的谓词编程指南:
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];
推荐的方法是使用Apple Recommended Method NSExpression。 我认为这比使用sorting要便宜。如果你仔细想想,用一种sorting,你将不得不把所有的loggingsorting,并保持最大的一个。 有了一个expression式,你只需要通读列表,并保持在记忆中的最大值。
这里是我使用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; }
上面使用NSExpression给出的答案是正确的。 这是Swift版本。
private func getLastContactSyncTimestamp() -> Int64? { let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest() request.entity = NSEntityDescription.entity(forEntityName: "Contact", 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。
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) }