核心数据输入非常慢

时间:2016-07-12 10:06:02

标签: ios objective-c json core-data nsmanagedobject

开发一个需要从Json导入不同表中的数据的应用程序。我对所有表都使用泛型函数。问题是当表有很多记录时输入速度极慢。

parseJSON函数:

-(NSManagedObject *)getManagedObjectForEntity:(NSString *)entityName primaryKey:(NSDictionary *)key jsonEntity:(NSString *)jsonEntity json:(NSDictionary *)json{

NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSArray *primaryKeyName = [key allKeys];
NSMutableArray *subpredicates = [NSMutableArray array];
NSError *error = nil;
NSArray *managedObjectArray = [[NSArray alloc] init];
for (NSString *k in primaryKeyName) {
    NSPredicate *predicate;
    NSString *value = [key objectForKey:k];
    predicate = [NSPredicate predicateWithFormat:@"(%K == %@)",k,value];

    [subpredicates addObject:predicate];
}
NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];

[request setPredicate:predicate];

NSError *error = nil;
managedObjectArray = [context executeFetchRequest:request error:&error];

if (managedObjectArray == nil)
{
    // Deal with error...
}


if ([managedObjectArray count] > 0)
    return [managedObjectArray firstObject]; //Object exists

//If object is not found lets create it

NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];

NSDictionary *allAttributes = [entityDescription attributesByName];
NSDictionary *allRelationships = [entityDescription relationshipsByName];

NSArray *allAttributesName = [allAttributes allKeys];

for (NSString *k in primaryKeyName) {
    if ([allAttributesName containsObject:k]) {
        //Key is an attribute
        [managedObject setValue:[key objectForKey:k] forKey:k];
    }
    else {

        //Key is a relationship
        NSString *relationshipKey = [[k componentsSeparatedByString:@"."] firstObject];
        NSRelationshipDescription *oneRelationship = [allRelationships objectForKey:relationshipKey];

        NSString *destEntityName = [[oneRelationship destinationEntity] name];
        NSArray *destEntityPrimaryKey = [self getPrimaryKeyNameForEntity:destEntityName];

        NSArray *destEntityPrimaryKeyValues = [json objectsForKeys:[self getPrimaryKeyNameForEntity:destEntityName inJSONEntity:jsonEntity attrName:relationshipKey] notFoundMarker:@""];

        NSManagedObject *destManagedObj = [self getManagedObjectForEntity:destEntityName primaryKey:[NSDictionary dictionaryWithObjects:destEntityPrimaryKeyValues forKeys:destEntityPrimaryKey] jsonEntity:jsonEntity json:json];

        [managedObject setValue:destManagedObj forKey:relationshipKey];
    }
}

return managedObject;
}

getManagedObjectForEntity函数(这里我们在数据库中查找托管对象,如果不存在则创建它):

$('input[name="p-color"]').keyup(function() {
  var pColor = ($(this).val());
  $('.custom-style-demo p').css({"color":pColor});
});
$('input[name="heading-color"]').keyup(function() {
  var headingColor = ($(this).val());
  $('.custom-style-demo h1, .custom-style-demo h2, .custom-style-demo h3').css({"color":headingColor});
});

最后,我在导入所有JSON数据时使用[context save:& error]函数。

我尝试将每个表保存在一个数组中,并在数组中查找托管对象,但每个表中的大量数据都会导致内存问题。 有没有更好的方法来更快地导入所有这些数据? 感谢

1 个答案:

答案 0 :(得分:1)

查找和创建模式总是很昂贵。但是,您的设计正在为每个个人记录访问磁盘。这很浪费,很可能是你缓慢的核心。

如果您使用的是iOS 8或更早版本,那么您应该使用KVC一次获取所有主键并同时获取所有现有记录(或者至少是NSManagedObjectID),然后您可以制作决定插入或更新。

如果您使用的是iOS 9或更新版本,则更容易,因为您可以将主键设置为持久存储中的约束(假设您使用的是SQLite),然后只需插入所有记录并让Core Data解决插入与更新问题。

至于内存压力,您很可能希望在导入期间中断作业并保存几次。每当你保存时,你可以在上下文中调用-reset来要求它从内存中删除它的对象。这将有助于你减轻压力。

最后,使用仪器。虽然我上面给出的一般建议会有所帮助,但您可以使用时间分析器并在自己的代码中查找热点来微调导入。