我目前正在开发一款通过网络服务下载大量联系人的应用,并将解析后的数据插入到iOS通讯录中。因为应用程序的用户拥有10-15万个联系人并非闻所未闻,我最初的方法是将事情分解为离散操作(一个操作是下载/解析/插入1500个联系人)并让它们单独运行的背景。例如,如果我要下载20000多个联系人,代码将类似于以下内容。
for(int i = 0; i < 20047; i+=1500)
{
NSString* url = [NSString stringWithFormat:@"http://XXXXXX.XXXX/XXXXX"];
NSString* urlEncodedString = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *URL = [NSURL URLWithString:urlEncodedString];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^()
{
[self parseJSON:responseObject];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
[self.downloadQueue addOperation:op];
}
作为参考,“parseJSON”函数看起来大致如下:
CFErrorRef error = NULL;
ABAddressBookRef ab = ABAddressBookCreateWithOptions(NULL, &error);
for(NSDictionary* _contactInfo in _contacts)
{
ABRecordRef aRecord = ABPersonCreate();
.............
//Strip the record info and insert it into the ABRecordRef
.............
//Add the record to the previously created group (ID equal to 1 in this case.)
if(ABAddressBookAddRecord(ab, aRecord, nil))
{
ABRecordRef ieGroup = ABAddressBookGetGroupWithRecordID(ab,1);
ABGroupAddMember(ieGroup, aRecord, nil);
}
CFRelease(aRecord);
}
ABAddressBookSave(ab, nil);
CFRelease(ab);
当联系人数量小于10000时,这种方法似乎运行良好,但在15000范围内开始崩溃。我已经能够下载16000多个联系人,但它往往是不稳定的,并且习惯在ABAddressBookSave函数的12000标记附近崩溃。
在进行一些简单的时序测试时,似乎最大的瓶颈是ABAddressBookSave。每个后续的保存操作都需要更长和更长的时间(大约几分钟,而不是几秒),这并不是特别令人惊讶,因为我猜测每个操作都需要等待更长时间才能锁定前一个操作才能完成。
我的问题是,是否有人处理过此类情况以及是否有更好的解决方案?下载/解析/插入所有顺序是一个更好的想法,更不容易出现问题?