2014-09-26 97 views
1

在iOS8(iPhone 5s)中获取联系人会导致随机崩溃。 崩溃细节:http://hastebin.com/ukihinucaf.md在iOS8中获取联系人列表,崩溃应用程序

在行:

ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty); 

这里是全功能:

-(NSArray *) getAllContacts 
{ 

    CFErrorRef *error = nil; 

    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error); 

    __block BOOL accessGranted = NO; 
    if (ABAddressBookRequestAccessWithCompletion != NULL) { 
     dispatch_semaphore_t sema = dispatch_semaphore_create(0); 
     ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { 
      accessGranted = granted; 
      dispatch_semaphore_signal(sema); 
     }); 
     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 

    } 
    else { 
     accessGranted = YES; 
    } 

    if (accessGranted) { 

     ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error); 
     ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook); 
     CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName); 
     CFIndex nPeople = ABAddressBookGetPersonCount(addressBook); 
     NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople]; 
     for (int i = 0; i < nPeople; i++) 
     { 

      ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i); 

      //get Contact email 

      ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty); 

      for (CFIndex j=0; j<ABMultiValueGetCount(multiEmails); j++) { 
       CFStringRef contactEmailRef = ABMultiValueCopyValueAtIndex(multiEmails, j); 
       NSString *contactEmail = (__bridge NSString *)contactEmailRef; 

       [items addObject:contactEmail]; 
      } 

     } 
     return items; 

    } else { 
     NSLog(@"Cannot fetch Contacts :("); 
     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Fetch failed" message:@"Can't fetch your contacts." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; 
     [alert show]; 
     return nil; 

    } 
} 

任何人都知道什么是一个问题?

+1

难道是因为不能够妥善处理内存管理。您不会释放您创建或复制的所有CF对象,并且似乎有许多未被释放的对象。您的应用程序可能因内存警告而不是崩溃而死亡吗? – Sandeep 2014-09-26 22:00:10

+0

崩溃详细信息:EXC_BAD_ACCESS 0x0006000000000068上的KERN_INVALID_ADDRESS对于ABRecordCopyValue方法 – dormitkon 2014-09-26 22:08:03

+0

不是这是造成问题,而是'for'循环都使用变量'i'。总体来说这是有风险的 - 避免这种情况。 – rmaddy 2014-09-26 22:09:21

回答

2

您正在检索ABAddressBookGetPersonCount(所有来源中的所有人的数量,而不仅仅是默认来源中的人数),并在迭代数组时使用该阈值作为上限。但是该数组并不包含地址簿中的所有人员,而只包含默认数据源中的人员。因此,您可能会超出阵列中的项目数量。

我建议使用CFArrayGetCount而不是ABAddressBookGetPersonCount

+0

你说得对。我已经修复它使用: NSArray * allPeoplearray =(__bridge NSArray *)allPeople; CFIndex nPeople = allPeoplearray.count; 但您的方式更优雅:) – dormitkon 2014-09-26 22:32:05

+0

我刚刚使用了Core Foundation技术,因为您的代码示例使用Core Foundation来遍历数组。但我更喜欢你的方法是好的(尽管我使用'__bridge_transfer'或'CFBridgingRelease',它将所有权转移给ARC,并在数组超出范围时释放数组),然后退出CFArray函数。与电子邮件地址相同,例如'NSString * contactEmail = CFBridgingRelease(ABMultiValueCopyValueAtIndex(multiEmails,j));'。 – Rob 2014-09-27 01:34:41

2

ABAddressBookCreateWithOptions(NULL,error);

应该是这个

CFErrorRef error = NULL; 
ABAddressBookCreateWithOptions(NULL, &error); 
+0

这是捕获错误的正确方法。 – Rob 2015-08-12 21:32:57

相关问题