I'm trying to find the oldest date in a particular attribute in Core Data. I've found an example in the Core Data Programming Guide that purports to do exactly that, but keep getting an unrecognized selected error when I run it.
My code (with only minimal changes from the Apple Example):
NSFetchRequest *request = [[NSFetchRequest alloc] 开发者_StackOverflow中文版init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Session" inManagedObjectContext: ctx];
[request setEntity:entity];
// Specify that the request should return dictionaries.
[request setResultType:NSDictionaryResultType];
// Create an expression for the key path.
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"startedAt"];
// Create an expression to represent the minimum value at the key path 'creationDate'
NSExpression *minExpression = [NSExpression expressionForFunction:@"min:" arguments:[NSArray arrayWithObject:keyPathExpression]];
// Create an expression description using the minExpression and returning a date.
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
// The name is the key that will be used in the dictionary for the return value.
[expressionDescription setName:@"minDate"];
[expressionDescription setExpression:minExpression];
[expressionDescription setExpressionResultType:NSDateAttributeType];
// Set the request's properties to fetch just the property represented by the expressions.
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
// Execute the fetch.
NSError *error;
NSArray *objects = [ctx executeFetchRequest:request error:&error];
And the error:
-[NSCalendarDate count]: unrecognized selector sent to instance ...
Which is strange given that 1) NSCalendarDate is deprecated and 2) I'm definitely not calling count.
Any help would be most appreciated!
Why not just add a sort descriptor to sort by startedDate
ascending, and then only have the fetch request return 1 object?
This is my code which does work. I cannot see any significant difference to your own code and perhaps it is in the definition of the core data model. Make sure your date is NSDate and it is indexed.
- (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;
}
精彩评论