如何在核心数据上实现瞬态属性?

时间:2014-10-01 22:54:01

标签: ios cocoa-touch core-data nsmanagedobject nsfetchedresultscontroller

我有一个名为Countries的核心数据实体。该实体有一个名为nameOfCountry的字段,其中包含英文的国家/地区名称。我需要将其本地化为其他语言,因此我创建了一个名为nameOfCountryLocalized的瞬态属性。

在我要导入此类别的国家/地区类

国家+ NameOfCountryLocalized.h

#import "Countries.h"

@interface Countries (NameOfCountryLocalized)


@property (nonatomic, strong) NSString * nameOfCountryLocalized;


@end

国家+ NameOfCountryLocalized.m

#import "Countries+NameOfCountryLocalized.h"
#import "Countries.h"

@implementation Countries (NameOfCountryLocalized)

@dynamic nameOfCountryLocalized;


-(NSString *) nameOfCountryLocalized {
  [self willAccessValueForKey:@"nameOfCountryLocalized"];
  NSString *nameLocalized = NSLocalizedString(self.nomePais, nil);
  [self didAccessValueForKey:@"nameOfCountryLocalized"];
  return nomeLocalizado;
}

-(void)setNameOfCountryLocalized:(NSString *) nameLocalized {
  [self willChangeValueForKey:@"nameOfCountryLocalized"];
  [self setNomePaisLocalizado:];
  [self didChangeValueForKey:@"nameOfCountryLocalized"];
}

@end

当我尝试使用tableViewController

访问nameOfCountryLocalized时
- (NSFetchedResultsController *)fetchedResultsController {

  if (_fetchedResultsController != nil) {
    return _fetchedResultsController;
  }


  NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
  NSEntityDescription *entity = [NSEntityDescription
                                 entityForName:@"Countries" inManagedObjectContext:self.managedObjectContext];
  [fetchRequest setEntity:entity];

  NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"nameOfCountryLocalized" ascending:YES];
  [fetchRequest setSortDescriptors:@[sort]];

  [fetchRequest setFetchBatchSize:20];

  NSFetchedResultsController *theFetchedResultsController =
  [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                      managedObjectContext:self.managedObjectContext
                                        sectionNameKeyPath:nil
                                                 cacheName:@"Root"];

  _fetchedResultsController = theFetchedResultsController;
  _fetchedResultsController.delegate = self;

  return _fetchedResultsController;

}

我看到此错误:在实体中找不到keypath nameOfCountryLocalized

任何线索?

2 个答案:

答案 0 :(得分:4)

NSFetchedResultsController不能通过瞬态属性排序。 FRC将排序应用于基础SQL存储。利用瞬态属性,FRC可以分组获取分段的结果。通过将transient属性分配给sectionNameKeyPath来创建

一旦数据增长,将所有实体拉入数组将变得很痛苦。 FRC确实为更大的数据集提供了很好的支持,你真的不想放松它。

您可能会认为您的用户不经常切换语言。如果是这种情况,我建议您将本地化的国家/地区名称作为“普通”属性写入商店,FRC可以对该属性进行排序。 虽然当用户切换语言时,您需要更新所有国家/地区实体。

答案 1 :(得分:1)

您的Countries课程不是实体。它是数据库中单个对象的类。

您确实应该将其重命名为Country,因为将NSManagedObject子类称为复数是不正确的。这就是Apple没有为班级NSManagedObjects命名的原因。

因为您的属性被添加到单个对象而不是实体本身,所以只有在从数据库中提取对象后才能使用它。它不能用作获取对象的一部分。

您需要先将结果(所有这些)都提取到NSArray,然后将NSSortDescriptor应用于NSArray对对象进行排序。您可能希望通过围绕NSFetchedResultsController创建包装类来实现此目的。

或者,将nameOfCountryLocalized属性放在实际数据库中,使用英文值,然后如果用户没有使用英文写入数据库,则将所有内容更改为正确的值。这样您就可以完全按照您现在尝试的方式使用NSFetchedResultsController。如果您的数据库很庞大,我推荐这种方法......但事实并非如此,世界上只有几百个国家,因此性能完全没有问题。