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检查本身不会这样做),但是这个值将是垃圾,当你试图复制它的任何值时,你将得到不良的访问。
希望这可以帮助。