当我尝试将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
答案 0 :(得分:2)
首先要做的是运行仪器并找到瓶颈,正如@jrturton建议的那样。
但是,通过阅读代码可以看出一个巨大的明显瓶颈。为避免重复,您需要为每个传入实例执行fetch。有了4万条记录,您在导入过程中必须进行4万次提取,无论如何都会变慢。
您可以通过批量处理数据来改善这一点:
caseNumber
值添加到数组中caseNumber IN %@
进行提取,数组作为参数。你需要进行一些实验,看看有多少&#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];
}
}