减少在iphone应用上执行大操作的时间

问题描述:

当我启动应用程序时,我需要检索地址簿中的所有联系人&将其存储在数组中以在表格视图中显示它。我在viewDidAppear方法中编写了这段代码。当联系人正在从地址簿中检索时,我正在显示活动指示器。我的地址簿中有大约1100个联系人。为此,花费14秒钟检索数据&将其存储在数组中。这是不可接受的时间。所以我需要优化这个减少时间到最多2到3秒。减少在iphone应用上执行大操作的时间

我需要所有的联系人,因为当我的应用程序启动时,我需要搜索联系人,所以我需要我的数组中可用的所有数据。

如何减少此时间?如果您需要更多信息,请告诉我。 高度赞赏任何形式的帮助。谢谢。

更新1:我的代码

- (NSMutableArray*)getAddressBookData { 

    self.tempArray = [[NSMutableArray alloc]init]; 
    addressBook = ABAddressBookCreate(); 
    APP_DELGATE.people = (NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook); 
    peopleCount = [APP_DELGATE.people count]; 

    for (int i=0; i<peopleCount; i++) { 

     ABRecordRef record = [APP_DELGATE.people objectAtIndex:i]; 

     NSNumber *recordId = [NSNumber numberWithInteger:ABRecordGetRecordID(record)]; 
     NSLog(@"record id is %@",recordId); 

     // Get fname, lname, company 
     NSString *fnm = (NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty) ; 
     NSString *lnm = (NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty) ; 
     NSString *comp = (NSString*)ABRecordCopyValue(record,kABPersonOrganizationProperty); 

     // Get Ph no 
     ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(record, kABPersonPhoneProperty); 
     NSArray* phoneNumbers = [self getPhoneNoWithoutSymbols:(NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty)]; 
     NSString *strPhoneNos = [self getStringRepresentaionFromArray:phoneNumbers]; 
     NSLog(@"strPhoneNos => %@",strPhoneNos); 

     // Get emails 
     ABMultiValueRef emailProperty = ABRecordCopyValue(record, kABPersonEmailProperty); 
     NSArray* emails = (NSArray*)ABMultiValueCopyArrayOfAllValues(emailProperty); 
     NSString *strEmails = [self getStringRepresentaionFromArray:emails]; 
     NSLog(@"strEmails => %@",strEmails); 

     // Get URL 
     ABMultiValueRef urlProperty = ABRecordCopyValue(record, kABPersonURLProperty); 
     NSArray* urls = (NSArray*)ABMultiValueCopyArrayOfAllValues(urlProperty); 
     NSString *strURLs = [self getStringRepresentaionFromArray:urls]; 
     NSLog(@"strURLs => %@",strURLs); 

     // Get Address 
     ABMultiValueRef address=ABRecordCopyValue(record, kABPersonAddressProperty); 
     CFDictionaryRef dic=nil; 
     NSMutableArray *addressArray = [[NSMutableArray alloc]init]; 
     for (int index=0; index<ABMultiValueGetCount(address); index++) { 

      dic=ABMultiValueCopyValueAtIndex(address, index); 
      NSString* labelName=(NSString*)ABMultiValueCopyLabelAtIndex(address, index); 

      if (labelName) { 

       NSString *street =(NSString*) CFDictionaryGetValue(dic, kABPersonAddressStreetKey); 
       NSString *city= (NSString*)CFDictionaryGetValue(dic, kABPersonAddressCityKey) ; 
       NSString *state= CFDictionaryGetValue(dic, kABPersonAddressStateKey); 
       NSString *country=CFDictionaryGetValue(dic, kABPersonAddressCountryKey); 
       NSString *zipcode=CFDictionaryGetValue(dic, kABPersonAddressZIPKey); 

       NSString *[email protected]""; 
       if (street) { 
        addressDetails=[NSString stringWithFormat:@"%@ ",street]; 
       } 
       if (city) { 
        addressDetails=[NSString stringWithFormat:@"%@ %@ ",addressDetails,city]; 
       } 
       if (state) { 
        addressDetails=[NSString stringWithFormat:@"%@ %@ ",addressDetails,state]; 
       }      
       if (country) { 
        addressDetails=[NSString stringWithFormat:@"%@ %@ ",addressDetails,country]; 
       } 
       if (zipcode) { 
        addressDetails=[NSString stringWithFormat:@"%@ %@ ",addressDetails,zipcode]; 
       } 

       [addressArray addObject:addressDetails]; 

      } 

     } 

     NSString *strAddress = [self getStringRepresentaionFromArray:addressArray]; 
     NSLog(@"strAddress => %@",strAddress); 

     // Get Notes 
     NSString *noteString=(NSString *)ABRecordCopyValue(record, kABPersonNoteProperty); 

     // Get Birthdate 
     NSDate *birthDate=(NSDate*)ABRecordCopyValue(record, kABPersonBirthdayProperty) ; 
     NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
     [formatter setDateFormat:@"MMMM dd yyyy"]; 
     NSString *birthdateString = [formatter stringFromDate:birthDate]; 
     [formatter release]; 

     // Get user image 
     UIImage *image = nil; 
     if(ABPersonHasImageData(record)) { 
      NSData *imageData = (NSData*)ABPersonCopyImageData(record); 
      image = [UIImage imageWithData:imageData]; 
      [imageData release]; 
     } 

     // Create User object & add it to array 
     User *user = [[User alloc]initUserWithUniqID:recordId.intValue FirstName:fnm lastName:lnm company:comp phoneNumbers:strPhoneNos emails:strEmails urls:strURLs address:strAddress notes:noteString dob:birthdateString userImage:image]; 

     [self.tempArray addObject:user]; 
     [user release]; 
    } 

    self.tempArray = [NSMutableArray arrayWithArray:[self.tempArray sortedArrayUsingSelector:@selector(compare:)]]; 

    APP_DELGATE.allUsersArray = self.tempArray; 
    return tempArray; 
} 



-(NSMutableArray*)getPhoneNoWithoutSymbols:(NSArray*)array { 

    self.phNoArray = [[NSMutableArray alloc]init]; 
    for (NSString *str in array) { 
     [self.phNoArray addObject:[self getPhNo:str]]; 
    } 
    return self.phNoArray; 
} 

-(NSString*)getPhNo:(NSString*)str { 

    NSString *str0 = [str stringByReplacingOccurrencesOfString:@" " withString:@""]; 
    NSString *str1 = [str0 stringByReplacingOccurrencesOfString:@"(" withString:@""]; 
    NSString *str2 = [str1 stringByReplacingOccurrencesOfString:@")" withString:@""]; 
    NSString *str3 = [str2 stringByReplacingOccurrencesOfString:@"-" withString:@""]; 
    return str3; 
} 

-(NSString*)getStringRepresentaionFromArray:(NSArray*)array { 

    return [array componentsJoinedByString:DELIMITER_SYMBOL]; 
} 
+0

我的建议是获取批量和辅助线程(使用dispatch_async)接触,然后当他们被提取,更新的tableView当主线程的代码返回。您可以添加一个小的加载图标,以便用户知道完整的地址簿何时加载 – justin 2012-03-31 16:45:22

+1

感谢您的回复。你能否详细说明“批量获取联系人”,因为如果我获取20条记录(例如)如何执行搜索?目前我的搜索查询只能对付20条记录。纠正他们,如果我错了。 – iOSAppDev 2012-03-31 16:57:54

+0

请显示您用于将地址簿中的数据加载到数组中的代码。也许一些缓存机制可以用来减少后续启动应用程序的启动时间。 Slev的建议也很好。如果您加载批量,确实只能执行搜索加载到内存中的部分,但它可以为用户提供更好的体验。 – 2012-03-31 18:00:41

  1. 执行您的联系人检索方法诊断和确定哪些电话在这里造成的瓶颈。
  2. 分享您的代码,并描述了瓶颈

任何操作应采取在一个线程中执行的时间严重金额。在这种情况下,我只会在首次启动时收集数据并将其存储在内部。您可以随时根据需要刷新主要数据(刷新按钮?),否则使用内部存储的联系人“克隆”,而不是在每个应用程序的启动时调用任何耗时的操作。

BTW:小心与地址簿中的联系人,这些天:-)

+0

感谢您的回复。 “现在注意地址簿联系人”是什么意思? – iOSAppDev 2012-03-31 16:58:29

+0

他的意思是确保在从地址簿中检索信息之前请求许可! – shabbirv 2012-03-31 17:01:22

+0

为什么?因为我从未阅读过“在从地址簿中获取信息之前请求许可”。无论如何感谢这一点。 – iOSAppDev 2012-03-31 17:08:47

首先,尝试一些通用的方法,通过使用更优化的代码的代码少重复和还通过更少的减少时间使用循环或可能是只迭代循环,直到获得数据。您还可以检查您的代码是否正确分发,就时间分析而言。

其次,我们觉得所需的时间更多,因为用户显示一个活动指示器,直到14秒。如果你没有显示它,并且不会阻止用户界面,直到数据被复制到你的阵列中,那么用户可能会觉得它更平滑所以这里是你如何做到这一点:

你可以使用NSThread允许应用程序在您从AddressBook中检索所有数据并将其存储在阵列中时启动。

您可以使用

[NSThread detachNewThreadSelector:@selector(fetchAddressContacts:) withObject:nil]; 

欲了解更多信息,可以参考detachNewThreadSelector: from NSThread

所以基本上在AppDelegate需要代码作为AppDelegate.m以下

-(void)applicationDidFinishLaunching:(UIApplication *)application { 
     [NSThread detachNewThreadSelector:@selector(fetchAddressContacts) withObject:nil]; 
} 

-(void)fetchAddressContacts { 
     //Do your stuff to copy your contacts from address book to array 
     // Once you finish this task you can trigger an NSNotification which could be caught on some other viewController or implement a delegate to transfer data to a viewController and proper actions can be executed once the data is loaded. 
} 

让我知道,如果你需要更多的帮助。

希望这可以帮助你。

+0

我编辑了我的答案。请参考它。 – 2012-04-01 14:28:51

+0

如果我使用detachNewThreadSelector,我的应用程序启动,然后直到数据载入表视图 – iOSAppDev 2012-04-02 09:21:47

+0

@appDev用户无法看到任何东西:一旦你加载的tableView,则可以显示MBPorgressHUD呈现出“加载数据。”在其标题。直到你的数据加载。通过这种方式,用户可以获知应用程序尚未挂起并正在继续前进。 – 2012-04-02 09:26:49

当你的应用第一次安装获取所有的联系人,并保存在coredate/plist文件时,下一次打开应用程序,然后从显示这是非常快,比较取出由iPhone数据库中的联系人存储的联系人。现在的问题是如何更新新添加的联系人,因此每个联系人都有名为“kABPersonModificationDateProperty”和“kABPersonCreationDateProperty”的属性,使用它仅查找更新的联系人并添加到存储中。希望这可以帮助。