【问题标题】:NSPredicate: Fetch one of each kindNSPredicate:获取每种类型的一个
【发布时间】:2013-05-01 17:48:00
【问题描述】:

我想为这样的对象创建一个NSFetchRequest

ObjectCar,它有一个 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];
          }
          

          【讨论】:

            猜你喜欢
            • 2013-05-01
            • 2012-03-02
            • 1970-01-01
            • 2023-04-07
            • 1970-01-01
            • 2014-05-09
            • 1970-01-01
            • 1970-01-01
            • 2010-11-24
            相关资源
            最近更新 更多