【问题标题】:NSPredicate: Fetch one of each kindNSPredicate:获取每种类型的一个
【发布时间】:2013-05-01 17:48:00
【问题描述】:
我想为这样的对象创建一个NSFetchRequest:
Object 是 Car,它有一个 attribute color。
我有四辆车:
car1.color = red
car2.color = red
car3.color = blue
car4.color = green
我想创建一个NSPredicate,它只为每种颜色选择一辆汽车(它选择哪辆汽车并不重要。
我怎样才能做到这一点?
事实上,我正在寻找类似于 SQL 中的 DISTINCT 的东西
【问题讨论】:
标签:
iphone
ios
objective-c
nspredicate
nsfetchedresultscontroller
【解决方案1】:
Core Data确实支持获取不同的值。苹果甚至在这里提供了示例代码:http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/fetchExpressions.html
从那个页面:
获取不同的值
获取所有特定属性的唯一值
给定实体的实例,您可以使用
方法 setReturnsDistinctResults: (并传递 YES 作为参数)。你
还指定 fetch 应该返回字典而不是
托管对象,以及您要获取的属性的名称。
Swift 2.0
let context:NSManagedObjectContext! = <#Get the context#>
let entity = NSEntityDescription.entityForName( "<#Entity name#>", inManagedObjectContext:context )
let request = NSFetchRequest()
request.entity = entity
request.resultType = .DictionaryResultType
request.returnsDistinctResults = true
request.propertiesToFetch = [ "<#Attribute name#>" ]
var objects:[[String:AnyObject]]?
do
{
try objects = context.executeFetchRequest( request )
}
catch
{
// handle failed fetch
}
Obj-C
NSManagedObjectContext *context = <#Get the context#>;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"<#Entity name#>" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:YES];
[request setPropertiesToFetch:@[@"<#Attribute name#>"]];
// Execute the fetch.
NSError *error = nil;
id requestedValue = nil;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil) {
// Handle the error.
}
(一个“陷阱”是结果将作为字典返回——如果您需要对象,您可以通过 ID 再次获取它们)
【解决方案2】:
您是否尝试使用 valueForKeyPath ?你可以在 NSPredicate 提供给你的数组中做类似的事情。
NSArray* distinctColors = [cars valueForKeyPath:@"@distinctUnionOfObjects.color"];
它会返回给你你所拥有的独特颜色,我不知道它是否是你想要的,但你可以用这些颜色做类似@Anupdas 所说的事情:
【解决方案3】:
如果您的目标是 iOS 4.0 或更高版本并且不使用 Core-Data SQL 存储,为什么不使用predicateWithBlock:?
下面会生成你想要的NSFetchRequest。
- (NSFetchRequest*) fetchRequestForSingleInstanceOfEntity:(NSString*)entityName groupedBy:(NSString*)attributeName
{
__block NSMutableSet *uniqueAttributes = [NSMutableSet set];
NSPredicate *filter = [NSPredicate predicateWithBlock:^(id evaluatedObject, NSDictionary *bindings) {
if( [uniqueAttributes containsObject:[evaluatedObject valueForKey:attributeName]] )
return NO;
[uniqueAttributes addObject:[evaluatedObject valueForKey:attributeName]];
return YES;
}];
NSFetchRequest *req = [NSFetchRequest fetchRequestWithEntityName:entityName];
req.predicate = filter;
return req;
}
然后您可以创建一个新方法来执行提取并返回您想要的结果。
- (NSArray*) fetchOneInstanceOfEntity:(NSString*)entityName groupedBy:(NSString*)attributeName
{
NSFetchRequest *req = [self fetchRequestForSingleInstanceOfEntity:entityName groupedBy:attributeName];
// perform fetch
NSError *fetchError = nil;
NSArray *fetchResults = [_context executeFetchRequest:req error:&fetchError];
// fetch results
if( !fetchResults ) {
// Handle error ...
return nil;
}
return fetchResults;
}
【解决方案4】:
试试这个:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity =
[NSEntityDescription entityForName:@"Selected_data"
inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *predicatecnName = [NSPredicate predicateWithFormat:@"countries contains[cd] %@", Countryid];
NSPredicate *predicateLn = [NSPredicate predicateWithFormat:@"languages contains[cd] %@", languageid];
NSArray *subPredicates = [NSArray arrayWithObjects:predicatecnName, predicateLn, nil];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
[request setPredicate:predicate];
NSMutableArray *sendfd=[[NSMutableArray alloc] init];
NSError *error;
NSArray *array1 = [self.managedObjectContext executeFetchRequest:request error:&error];
if (array1 != nil) {
for (Selected_data *sld in array1)
{
[sendfd addObject:sld.providers];
}
}
else {
}
return sendfd;
【解决方案5】:
试试这个:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Cars"];
NSArray *arrayValues = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (arrayValues.count != 0) {
NSDictionary *result = [NSDictionary dictionaryWithObjects:arrayValues
forKeys:[arrayValues valueForKey:@"color"]];
return [result allValues];
}