【问题标题】:How to implement a transient property on core data?如何在核心数据上实现瞬态属性?
【发布时间】:2014-11-26 22:04:40
【问题描述】:

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

在 Country 类中我正在导入此类别

Countries+NameOfCountryLocalized.h

#import "Countries.h"

@interface Countries (NameOfCountryLocalized)


@property (nonatomic, strong) NSString * nameOfCountryLocalized;


@end

Countries+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 not found in entity

有什么线索吗?

【问题讨论】:

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


    【解决方案1】:

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

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

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

    您需要先将结果(全部)提取到NSArray,然后通过将NSSortDescriptor 应用于NSArray 对对象进行排序。您可能想通过围绕NSFetchedResultsController 创建一个包装类来做到这一点。

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

    【讨论】:

    • 好的,但为什么我不能使用瞬态属性?我想有一种方法可以使用这种属性。但还没有想通。像往常一样,Apple 提供的文档很混乱。
    • Apple 的文档并不令人困惑,您误解了 Core Data 的工作原理。也许您需要回到基本的核心数据文档并从头开始重新学习所有内容。您编写的代码不起作用,因为 Core Data 的设计目的不是为了能够做您想做的事情。您需要采取完全不同的方法,我在回答中强调了这一点。
    【解决方案2】:

    NSFetchedResultsController 不能按瞬态属性排序。 FRC 将 sort 应用于底层 SQL 存储。借助瞬态属性,FRC 可以将获取的结果分组 到多个部分中。此是通过将瞬态属性分配给sectionNameKeyPath而创建的。

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

    假设您的用户不经常切换语言,您可能没问题。如果是这种情况,我建议您将本地化的国家/地区名称作为“正常”属性写入商店,FRC 可以对该属性进行排序。 尽管当用户确实切换语言时,您需要更新所有 Country 实体。

    【讨论】:

    • 我通过使用您在最后一段中所说的内容解决了这个问题,但是如果您可以将您在第一段中所说的内容放入代码中,那么很高兴知道这种其他形式的这样做。谢谢。
    • 关于如何分组的例子请看:stackoverflow.com/a/11331553/529243 上面的例子是按年份分组的,即一个数字(int)。如果要按国家或国家名称的首字母分组,则需要采用“yearOnly”方法中的代码。
    猜你喜欢
    • 1970-01-01
    • 2011-06-17
    • 2012-08-02
    • 2012-03-10
    • 2013-10-03
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 2013-06-26
    相关资源
    最近更新 更多