加载数据需要花费太多时间CoreData

时间:2015-01-29 06:32:09

标签: ios objective-c core-data

当我尝试将40,000条记录保存到CoreData实体时,我遇到了问题。

我通过使用AFNetworking使用Web服务获得40,000条记录,响应采用JSON格式。然后我将数据分成4个,10000个记录块,然后将这4个块分配给单独的NSOperation个对象(我创建了NSOperation的子类)并将这些NSOperation个对象添加到{{1 }}

问题在于,通过这种方式将数据保存到NSOperationQueue需要花费太多时间。我想找到一个可以非常快速地加载数据的解决方案。

这是我创建CoreData个对象并将其添加到NSOperation的代码。

NSOperationQueue

CaseOperation.h

 - (void)casesResponseReceived:(NSArray*)array
{
 id responseObject = [array objectAtIndex:0];
 NSManagedObjectContext *moc = [array objectAtIndex:1];

NSString *responseString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSArray *response = [responseString JSONValue];

NSString *responseStr = [response JSONRepresentation];
NSRange range = [responseStr rangeOfString:@"["];
int index = 0;
int objectsCount = 5000;
if (range.location == 0) {
    NSInteger count = objectsCount;
    totalOperationsCount = 0;
    completedOperationsCount = 0;
    self.myQueue = [[NSOperationQueue alloc] init];
    while (count == objectsCount) {
        if ((index+count) > [response count]) {
            count = [response count] - index;
        }
        NSArray *subArray = [response subarrayWithRange:NSMakeRange(index, count)];
        index += objectsCount;

        CaseParseOperation *operation = [[CaseParseOperation alloc] initWithData:subArray MOC:moc];
        operation.delegate = self;
        totalOperationsCount++;
        [self.myQueue addOperation:operation];

    }

    /*
    if (self.delegate && [self.delegate respondsToSelector:@selector(serviceHelperDidCasesReceivedSuccessful:)]) {
        [self.delegate serviceHelperDidCasesReceivedSuccessful:self];
    }*/
}
else {
    if (self.delegate && [self.delegate respondsToSelector:@selector(serviceHelperDidCasesReceivedFailed:)]) {
        [self.delegate serviceHelperDidCasesReceivedFailed:self];
    }
}}

CaseOperation.m

@class CaseParseOperation;

@protocol CaseParseOperationProtocol <NSObject>
-(void)caseParseOperationDidOperationComplete: (CaseParseOperation*)caseParseOperation;
 @end
 @interface CaseParseOperation : NSOperation
 @property (nonatomic, weak) id<CaseParseOperationProtocol> delegate;
 -(id)initWithData:(NSArray*)parseData MOC:(NSManagedObjectContext*)moc;
 @end

2 个答案:

答案 0 :(得分:2)

首先要做的是运行仪器并找到瓶颈,正如@jrturton建议的那样。

但是,通过阅读代码可以看出一个巨大的明显瓶颈。为避免重复,您需要为每个传入实例执行fetch。有了4万条记录,您在导入过程中必须进行4万次提取,无论如何都会变慢。

您可以通过批量处理数据来改善这一点:

  1. 将一堆caseNumber值添加到数组中
  2. 使用谓词caseNumber IN %@进行提取,数组作为参数。
  3. 使用该数组检查重复项。
  4. 你需要进行一些实验,看看有多少&#34;一堆&#34;在步骤1中。更高的数字意味着更少的提取,这有利于速度。但更高的数字也意味着更多的内存使用。

    有关更详细的讨论,请参阅Apple的Efficiently Importing Data指南,尤其是名为&#34;有效实施查找或创建的部分&#34;

答案 1 :(得分:0)

谢谢大家有价值的建议。但我通过改变parseData函数中的一些技术解决了这个问题。

-(void)parseData
  {
   NSString *predicateString = [NSString stringWithFormat:@"caseNumber == $caseNumber"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];

    NSArray *allCases = [Case getAllCaseObjectsWithMOC:self.localMOC];

    for (NSMutableDictionary *dic in self.casesData) {
        if (self.isCancelled) {
            break;
        }
        NSString *caseNo = [dic valueForKey:@"caseNo"];
        NSDictionary *variables = @{ @"caseNumber" : caseNo };

        predicate = [predicate predicateWithSubstitutionVariables:variables];

        NSArray *matchedObj = [allCases filteredArrayUsingPredicate:predicate];

        if ([matchedObj count] == 0) {
            NSString *desc = [dic valueForKey:@"description"];
            BOOL enabled = [[dic valueForKey:@"enabled"] boolValue];
            NSString *billToCustomerNo = [dic valueForKey:@"billToCustomerNo"];

            NSString *billToName = [dic valueForKey:@"billToName"];
            NSString *personResponsible = [dic valueForKey:@"personResponsible"];
            [Case createObjectWithCaseNumber:caseNo customerName:billToName customerAddress:@"" customerPhone:@"" caseDescription:desc customerNumber:billToCustomerNo isEnabled:enabled personResponsible:personResponsible MOC:self.localMOC];

        }
    }

       if ([self.localMOC hasChanges]) {
        [self.localMOC save:nil];
    }    
 }