【问题标题】:Insert Core Data models from json从 json 插入核心数据模型
【发布时间】:2014-06-24 18:15:48
【问题描述】:

我有一项服务可以获取使用以下 json 响应的员工:

[{ "initials": "PR", "name": "Paul", "accounts": ["SPA", "ITA"] },  
{ "initials": "SR", "name": "William", "accounts": ["ITA"] } ]

和另一个服务来获取导致这样的 json 的帐户:

[{ "code": "SPA", "name": "Spain", "employees": ["PR"]  },
 { "code": "ITA", "name": "Italy", "employees": ["PR", "SR"]  } ]

我需要解析接收到的信息并将其插入到核心数据数据库中,该数据库具有两个核心数据模型,员工和帐户,声明了多对多的关系。它们声明如下:

@interface Employee : NSManagedObject

    @property (nonatomic, retain) NSString *initials;
    @property (nonatomic, retain) NSString *name;
    @property (nonatomic, retain) NSSet *accounts;

@end

@interface Account : NSManagedObject

    @property (nonatomic, retain) NSString *code;
    @property (nonatomic, retain) NSString *name;
    @property (nonatomic, retain) NSSet *employees;

@end

我现在做的是先插入员工,然后创建每个帐户并查询要插入每个帐户的员工。显然,这样做的性能非常糟糕,因为我需要为每个帐户做一个请求。

- (void)loadEmployeesJSON { ... }
- (void)loadAccountsJSON {
    NSManagedObjectContext *context = self.managedObjectContext;

    NSError *err = nil;
    NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"Accounts" ofType:@"json"];
    NSArray *accounts = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath] options:kNilOptions error:&err];

    [accounts enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
        Account *account = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:context];
        account.code = [obj objectForKey:@"code"];
        account.name = [obj objectForKey:@"name"];
        account.employees = [self accountsForEmployee:[obj objectForKey:@"employees"]];
        NSError *error;
        if (![context save:&error]) {
            NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
        }
    }];
}

- (NSSet*)accountsForEmployee:(NSArray*)initialsArray {
    NSManagedObjectContext *context = self.managedObjectContext;
    NSError *error = nil;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:context];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"initials IN %@", initialsArray]];
    [fetchRequest setEntity:entity];
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    return [NSSet setWithArray:fetchedObjects];
}

如何在不要求每个帐户的员工的情况下链接它们? 我认为我可以在内存中映射所有员工并要求他们。但是,如果我的员工数据库太大(+100.000)而无法存储在内存中怎么办?

【问题讨论】:

  • 对您来说更好的方法可能是不使用多对多关系,而是只使用您在引用时懒惰地创建的只读帐户(和员工)属性。
  • 我不会推荐这种方法。它破坏了使用 Core Data 的意义。

标签: ios json xcode performance core-data


【解决方案1】:

无论大小有多大,您都可以将所有员工都保存在内存中。为此,在您创建员工实体并保存它(最好是批量保存)后,通过以下方式将它们重置为故障:

NSManagedObjectContext *moc = ...;
NSManagedObject *employee = ...;
[moc refreshObject:employee mergeChanges:NO];

通过在保存后调用-refreshObject:mergeChanges:,它将将该对象的属性和关系从内存中删除,并将其内存占用减少到接近于零。从那里您可以将其存储在NSDictionary 中以供以后进行关系映射。

这将避免所有的提取并显着提高您的导入性能。

【讨论】:

  • 您的意思是将员工 NSManagedObject 添加到 NSMutableDictionary(使用什么作为键)或将员工转换为 NSDictionary 并存储在数组中?
  • NSManagedObject 添加到字典中。使用您在 JSON 中使用的任何唯一 ID 作为您的密钥。然后,当您链接帐户时,您可以使用相同的唯一性来处理关系。
猜你喜欢
  • 2017-05-22
  • 1970-01-01
  • 2015-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-01
  • 2010-12-10
相关资源
最近更新 更多