开发一个需要从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]函数。
我尝试将每个表保存在一个数组中,并在数组中查找托管对象,但每个表中的大量数据都会导致内存问题。 有没有更好的方法来更快地导入所有这些数据? 感谢
答案 0 :(得分:1)
查找和创建模式总是很昂贵。但是,您的设计正在为每个个人记录访问磁盘。这很浪费,很可能是你缓慢的核心。
如果您使用的是iOS 8或更早版本,那么您应该使用KVC一次获取所有主键并同时获取所有现有记录(或者至少是NSManagedObjectID
),然后您可以制作决定插入或更新。
如果您使用的是iOS 9或更新版本,则更容易,因为您可以将主键设置为持久存储中的约束(假设您使用的是SQLite),然后只需插入所有记录并让Core Data解决插入与更新问题。
至于内存压力,您很可能希望在导入期间中断作业并保存几次。每当你保存时,你可以在上下文中调用-reset
来要求它从内存中删除它的对象。这将有助于你减轻压力。
最后,使用仪器。虽然我上面给出的一般建议会有所帮助,但您可以使用时间分析器并在自己的代码中查找热点来微调导入。