在iOS8中获取联系人列表,使应用程序崩溃

在iOS8中获取联系人列表,使应用程序崩溃,ios,objective-c,ios8,contacts,Ios,Objective C,Ios8,Contacts,在iOS8(iphone5s)中获取联系人会导致随机崩溃。 坠机详情: 第行: ABMultiValueRef multiEmails = ABRecordCopyValue(person, kABPersonEmailProperty); 以下是整个功能: -(NSArray *) getAllContacts { CFErrorRef *error = nil; ABAddressBookRef addressBook = ABAddressBookCreate

在iOS8(iphone5s)中获取联系人会导致随机崩溃。 坠机详情:

第行:

    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;

    }
}
-(NSArray*)获取所有联系人
{
CFErrorRef*错误=nil;
ABAddressBookRef addressBook=ABAddressBookCreateWithOptions(空,错误);
__block BOOL accessgrated=否;
if(ABAddressBookRequestAccessWithCompletion!=NULL){
dispatch\u semaphore\u t sema=dispatch\u semaphore\u create(0);
ABAddressBookRequestAccessWithCompletion(addressBook,^(已授予bool,CFErrorRef错误){
accessgrated=已授予;
调度信号量信号(sema);
});
调度信号量等待(永远调度时间);
}
否则{
accessgrated=是;
}
如果(已授予访问权限){
ABAddressBookRef addressBook=ABAddressBookCreateWithOptions(空,错误);
ABRecordRef source=ABAddressBookCopyDefaultSource(地址簿);
CFArrayRef allPeople=abAddressBookCopyArrayFallPeopleInSourceWithSortOrdering(addressBook、source、kABPersonSortByFirstName);
CFIndex nppeople=ABAddressBookGetPersonCount(地址簿);
NSMutableArray*items=[NSMutableArray阵列容量:NPEOPE];
for(int i=0;i对于(CFIndex j=0;j您正在检索
ABAddressBookGetPersonCount
(所有源中的所有人员计数,而不仅仅是默认源中的人员计数),并在遍历数组时将其用作上限阈值。但该数组不包含通讯簿中的所有人,而只包含默认源中的人。因此,您可能会超过数组中的项数


我建议使用
CFArrayGetCount
而不是
ABAddressBookGetPersonCount
您正在检索
ABAddressBookGetPersonCount
(所有源中所有人的计数,而不仅仅是默认源中的人数),并在遍历数组时将其用作上限阈值。但该数组不包含通讯簿中的所有人,而只包含默认源中的人。因此,您可能会超过数组中的项数


我建议使用
CFArrayGetCount
而不是
ABAddressBookGetPersonCount
ABAddressBookCreateWithOptions(NULL,error

应该是这个吗

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

ABAddressBookCreateWithOptions(空,错误

应该是这个吗

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

可能是因为无法正确处理内存管理。您没有释放您创建或复制的所有CF对象,并且似乎有许多对象没有释放。您的应用是否可能是由于内存警告而不是崩溃而被终止?崩溃详细信息:EXC\u坏访问内核\u无效\u地址ABRECORDCYVALUE方法的0x000600000000068不是因为这导致了问题,而是因为
for
循环都使用变量
i
。这通常是有风险的-避免这种情况。您还检索
ABAddressBookGetPersonCount
(所有源中所有人员的计数),并将其用作默认源中的人员的索引。还有其他问题(正如insane-36指出的,您没有释放内存;您使用
ABAddressBookCreateWithOptions
的错误参数的方式永远不会检索错误对象,如果有,我不会建议使用信号量模型,等等),但索引的潜在不匹配是主要问题。修复了索引,但问题仍然存在。可能是因为无法正确处理内存管理。您没有释放您创建或复制的所有CF对象,并且似乎有许多对象没有被释放。是否有可能t您的应用程序是由于内存警告而不是崩溃而被杀死的吗?崩溃详细信息:EXC_BAD_ACCESS KERN_INVALID_ADDRESS在0x000600000000068处用于ABRecordCopyValue方法不是因为这导致了问题,而是因为
for
循环都使用变量
i
。这通常是有风险的-避免这种情况。您还在检索
ABAddressBookGetPersonCount(所有源中所有人员的计数),并将其用作默认源中人员的索引。还有其他问题(正如insane-36所指出的,您没有释放内存;您使用
ABAddressBookCreateWithOptions
的错误参数的方式永远不会检索错误对象(如果有),我不会建议使用信号量模型等。),但索引的潜在不匹配是主要问题。修复了索引,但问题仍然存在。你是对的。我已经使用以下方法修复了它:NSArray allPeoplearray=(\uu-bridge NSArray)allPeople;CFIndex nppeople=allPeoplearray.count;但你的方法更优雅:)我只是使用了核心基础技术,因为您的代码示例是使用核心基础来迭代数组。但是实际上我更喜欢您的方法是好的(虽然我会使用<代码>、SypgigelType < /COD> >或<代码> CFBRGGIGORION ,它将所有权转移到ARC并在数组超出范围时释放它。,然后完全停用
CFArray
函数。与电子邮件地址相同,例如
NSString*contactEmail=cfbridgengrelease(ABMultiValueCopyValueAtIndex(multiEmails,j));
。你是对的。我已经使用:NSArray allPeoplearray=(\uu bridge NSArray)修复了它所有的人;cFixx nHuff= Apple PrimeRay.Calt;但是你的方式更优雅:我只是使用了核心基础技术,因为你的代码示例使用核心基础来迭代ARR。