具有不同属性的 NSFetchRequest

Posted

技术标签:

【中文标题】具有不同属性的 NSFetchRequest【英文标题】:NSFetchRequest with distinct properties 【发布时间】:2011-10-08 18:31:40 【问题描述】:

我正在尝试从 NSPredicate 获得不同的结果。

我的代码:

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Members" inManagedObjectContext:context];
    request.entity = entity;
    request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"city"
                                                                                     ascending:YES
                                                                                      selector:@selector(caseInsensitiveCompare:)]];

    request.predicate = [NSPredicate predicateWithFormat:@"memberDeleted == %@", [NSNumber numberWithBool:NO]];

    NSDictionary *properties = [entity propertiesByName];
    request.propertiesToFetch = [NSArray arrayWithObject:[properties objectForKey:@"city"]];
    request.returnsDistinctResults = YES;

    request.fetchBatchSize = 20;

    NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                          managedObjectContext:context
                                                                            sectionNameKeyPath:nil
                                                                                     cacheName:@"CityCache"];
    [request release];

    self.fetchedResultsController = frc;
    [frc release];

问题是结果多次返回同一个城市。这个Entity有很多Members,每个Member都有一个属性“city”。

我做错了什么?

谢谢,

强化学习

【问题讨论】:

【参考方案1】:

确保将NSFetchRequestresultType 设置为NSDictionaryResultType。默认是返回实际的对象,所以它会忽略propertiesToFetch

【讨论】:

我应该补充一点,NSFetchedResultsController 通常不是NSDictionaryResultType 的粉丝。你可能会遇到其他问题,不得不放弃NSFetchedResultsController 问题是我不希望结果是和 NSDictionary。如果没有,我将不得不更改我的一些代码。其他方式可行吗? 那么你希望它返回什么对象呢? Core Data 只能返回对象图中实际存在的对象。 我明白了。你是对的。我正在考虑获取成员,并按城市对它们进行分组。我没有 City 对象,所以你的建议是正确的。我的想法是错误的。不使用 NSFetchedResultsController 是最好的选择。你能更新答案,让其他人看得更清楚吗?【参考方案2】:

在@Alex 的帮助下,这是最终的代码,没有 FRC:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Members" inManagedObjectContext:self.managedObjectContext];
request.entity = entity;
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"city"
                                                                                 ascending:YES
                                                                                  selector:@selector(caseInsensitiveCompare:)]];

request.predicate = [NSPredicate predicateWithFormat:@"memberDeleted == %@", [NSNumber numberWithBool:NO]];

NSDictionary *properties = [entity propertiesByName];
request.propertiesToFetch = [NSArray arrayWithObject:[properties objectForKey:@"city"]];
request.returnsDistinctResults = YES;
request.resultType = NSDictionaryResultType;
request.fetchBatchSize = 20;

NSError *error = nil;
NSArray *tempArray = [self.managedObjectContext executeFetchRequest:request error:&error];

NSMutableArray *cities = [[NSMutableArray alloc] init];
for (int i=0; i < [tempArray count]; i++)
    NSDictionary *tempDict = [NSDictionary dictionary];
    tempDict = [tempArray objectAtIndex:i];

    if ([tempDict objectForKey:@"city"] != nil)
        [cities addObject:[tempDict objectForKey:@"city"]];


//if the tempArray has no nil values, it's more efficient with:
//NSArray* cities = [tempArray valueForKeyPath:@"city"];

self.cityArray = cities;
[cities release];
[request release];

这将返回一个带有城市列表的 NSArray。

谢谢。

【讨论】:

您可以更轻松地做到这一点。只需这样做:NSArray* cities = [tempArray valueForKeyPath:@"city"]; 这将为数组中的每个字典获取city 的值并将它们放入一个数组中。 @Alex,如果 Array 中没有 nil 值,则可以正常工作。如果有任何 nil 值,它就会崩溃。 糟糕。在调查这个问题时,我赞成 Rui 的“崩溃”评论,认为这是一个有价值的警告。但是 NSArray 类 ref 列出了一个稍微不同的方法,“valueForKey:”,它表示将为 nil 对象返回一个 NSNull 对象。所以应该没有问题。【参考方案3】:

来自官方文档:

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 :[NSArray arrayWithObject:@"<#Attribute name#>"]];

// Execute the fetch.
NSError *error;
id requestedValue = nil;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
if (objects == nil) 
    // Handle the error.

【讨论】:

以上是关于具有不同属性的 NSFetchRequest的主要内容,如果未能解决你的问题,请参考以下文章

具有命名属性和不同类型的任意命名索引属性的打字稿接口[重复]

如何在plsql中将对象类型属性的值分配给具有相同属性属性的不同对象类型?

在 C# 中创建一个每次都可以具有不同属性的类或对象

具有属性的对象可以为同一属性提供不同的类型

Kellerman Compare .NET Objects:比较具有不同属性名称的不同类型的对象

动态创建具有不同数量的属性和值的谓词