ABRecordCopyValue()EXC_BAD_ACCESS错误

在我的应用程序中,我必须检索用户联系人的某些属性。 例如,我需要检索联系人的名字,姓氏,中间名,昵称,组织,职位,部门,生日,电子邮件等。我有一些方法来检索这些属性,只有几个工作,即使他们都非常相似。 这里是我的一个方法正在工作(名字)和一个不是(职位)的代码:

+(NSString *)fetchFirstnameForPersonID: (NSUInteger)identifier{ NSString *firstName; ABRecordRef currentPerson = (__bridge ABRecordRef)[[PSAddressBook arrayOfContacts] objectAtIndex:identifier]; //If the first name property exists if ((__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty) != NULL){ firstName = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty); } //If the first name property does not exist else{ firstName = @"NULL"; } return firstName; } +(NSString *)fetchJobTitleForPersonID: (NSUInteger)identifier{ NSString *jobTitle; ABRecordRef currentPerson = (__bridge ABRecordRef)[[PSAddressBook arrayOfContacts] objectAtIndex:identifier]; if ((__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty) != NULL){ jobTitle = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty); } else{ jobTitle = @"NULL"; } return jobTitle; } 

arrayOfContacts是这样定义的类方法:

 +(NSArray *)arrayOfContacts{ //Creates an ABAddressBookRef instance containing the data from the address book database ABAddressBookRef addressBook = ABAddressBookCreate(); //Creates an NSArray from the CFArrayRef using toll-free bridging NSArray *arrayOfPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); CFRelease(addressBook); return arrayOfPeople; } 

这些方法在名为“PSPropertyFetcher”的模型类中定义。 在我的根视图控制器中,我在viewDidLoad中放置了一些NSLog语句来查看属性fetcher方法是否正常工作。 这是我的testing代码:

 NSLog(@"Property Fetchers Test\n"); for(NSUInteger i = 0; i <= ([PSAddressBook contactsCount]-1); i++){ NSLog(@"First Name: %@", [PSPropertyFetcher fetchFirstnameForPersonID:i]); NSLog(@"Middle Name: %@", [PSPropertyFetcher fetchMiddlenameForPersonID:i]); NSLog(@"Last Name: %@", [PSPropertyFetcher fetchLastnameForPersonID:i]); NSLog(@"Organization: %@", [PSPropertyFetcher fetchOrganizationForPersonID:i]); NSLog(@"Department: %@", [PSPropertyFetcher fetchDepartmentForPersonID:i]); NSLog(@"Job Title: %@\n\n", [PSPropertyFetcher fetchJobTitleForPersonID:i]); } 

这只是部分工作; 这是输出:

猜猜谁![80103:f803]属性撷取testing

猜猜谁![80103:f803]名字:Jod

猜猜是谁![80103:f803]中间名:鲍勃

2012-06-27 10:37:30.118猜猜谁![80103:f803]姓:Satson

猜猜谁![80103:f803]组织:约翰逊和约翰逊

猜猜是谁![80103:f803]部门:NULL

2012-06-27 10:37:30.128猜猜谁![80103:f803]职位名称:NULL


2012-06-27 10:37:30.136猜猜谁![80103:f803]名字:Shemairan

猜猜谁![80103:f803]中间名:Daitran

猜猜是谁![80103:f803]姓氏:Catairan

猜猜谁![80103:f803]组织:Shmairo and Co.

猜猜是谁![80103:f803]部门:NULL

2012-06-27 10:37:30.193猜猜谁![80103:f803]职位名称:NULL


猜猜谁![80103:f803]名字:亚历克斯

猜猜是谁![80103:f803]中名:约翰

2012-06-27 10:37:30.213猜猜谁![80103:f803]姓:玉米

猜猜谁![80103:f803]组织:苹果

2012-06-27 10:37:30.225猜猜谁![80103:f803]部门:NULL

2012-06-27 10:37:30.230猜猜谁![80103:f803]职位名称:NULL

在iOS模拟器联系人应用程序中,我确保填写每个联系人的每个字段,但出于某种原因,“部门”和“职位”字段未正确打印。

基本上,我想知道我的“职位”和“部门”提取方法有什么问题。

提前致谢!

虽然看起来不太可能在地址簿的这样一个小样本上,但是这里有一个内存泄漏,可能会把事情搞砸。

假设你正在使用arrayOfContacts来确定[self contactsCount] ,那么每次在这些类方法的每个循环中都会泄漏2个AddressBook项。

在这个小样本中,当您启动contactsWithJobTitleProperty时,您将只泄露48个AddressBook。 但是,如果你从一个更大的例子中反复尝试在一个更大的AddressBook上确定这些值,你可能会有数以百计的悬挂AddressBook对象。

添加CFRelease,如下面的代码片段,看看是否有帮助。

 +(NSArray *)arrayOfContacts{ //Creates an ABAddressBookRef instance containing the data from the address book database ABAddressBookRef addressBook = ABAddressBookCreate(); //Creates an NSArray from the CFArrayRef using toll-free bridging NSArray *arrayOfPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); CFRelease(addressBook); return arrayOfPeople; } 

(fwiw,会导致程序崩溃的一个单独的事情是,你使用NSUInteger作为你的循环计数器types,但是你testing的值可能是-1 …,因为0是NSUInteger的地板,如果你的地址本书没有联系,这将失败,但这不是为什么这个崩溃发生。)

它看起来像你可能正在访问一个NULL值,你有没有尝试过,如果它是NULL之前执行桥接传输?

这可能无法解决你的问题,但如果我是你,我会做一些调整:

 +(NSUInteger)contactsWithJobTitleProperty{ NSUInteger contactNumber = 0; // don't call arrayOfContacts in the loop -- // when you do this you are creating a new address book // each time the loop executes NSArray *contacts = [self arrayOfContacts]; for(NSUInteger increment = 0; increment <= (contacts.count-1); increment++){ ABRecordRef currentPerson = (__bridge ABRecordRef)[contacts objectAtIndex:increment]; NSString *valueTest = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty); if(valueTest != NULL) { contactNumber++; } } return contactNumber; } 

另外,@ john.k.doe提到,一定要使用CFRelease(addressBook); 在你的arrayOfContacts方法中。

刚刚遇到同样的问题。 在这里看到徐子's的回答 。

基本上,如果你有不同的联系人来源,而且他们并不都是本地的(默认的),你可能最终的结果是你的联系人数量不匹配,并尝试访问ABRecordRef在一个不存在的索引处。 ABRecordRef将有一个值(所以NULL检查本身不会这样做),但是这个值将是垃圾,当你试图复制它的任何值时,你将得到不良的访问。

希望这可以帮助。