我有一个应用程序偶尔会崩溃,因为ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering()返回的数组与ABAddressBookGetPersonCount()的大小不同。代码的shell如下所示。通常nPeople与数组大小相同。然而,在一个用户的iPhone上(或者至少,如一个用户所报告的那样),nPeople几乎是其两倍。我可以通过使用数组大小而不是ABAddressBookGetPersonCount()来停止崩溃。但是,我不确定这是否意味着我没有访问iPhone中的所有联系人。
我想知道这是否与存储在群组中的联系人有关(我不知道有群组 - 只是一个想法)。此外,从用户的电子邮件地址,我怀疑他们使用MobileMe。我想知道是否与MobileMe同步会创建具有不同recordId的重复项,但不会删除现有的Contact,至少不会像ABAddressBookGetPersonCount()那样。
编辑: 我已经对此进行了一些调查,并对问题的原因有了一个相当好的想法。由于我想要一个排序的联系人数组,我使用了ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering()。这需要一个地址簿源 - 我使用了默认源。我相信可以有各种来源 - 本地来源以及Exchange和MobileMe等其他来源。因此,我的数组最终将只有本地联系人,而ABAddressBookGetPersonCount()返回的数字将包括所有来源 - 因此我的崩溃。因此,我认为最好只使用我的应用程序中的本地数据,并使用ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering而不是ABAddressBookGetPersonCount返回的数组大小。
CFArrayRef allPeople = InSourceWithSortOrdering(addressBook, source, kABPersonSortByLastName);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for (int i = 0; i < nPeople; i++)
{
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
}
答案 0 :(得分:13)
ABAddressBookGetPersonCount而ABAddressBookCopyArrayOfAllPeople提供了不同的数组。
ABAddressBookGetPersonCount - 返回通讯录中的人员记录数。 ABAddressBookCopyArrayOfAllPeople - 返回地址簿中的所有人员记录。
所以有时候同一个人可能会有额外的记录。这就是为什么你可能会有不同的尺寸。
答案 1 :(得分:9)
我今天遇到了这个问题。我的应用程序也崩溃了一些特殊的iDevices。
代码:
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByLastName);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for (int i = 0; i < nPeople; i++) {
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
// more thing with `person`
}
但它有时会崩溃。添加一些断点我发现allPeople
的计数小于nPeople
。
通过Google搜索,我找到了this article。我发现ABAddressBookCopyDefaultSource
可能有问题。在这里我得到了默认来源,我必须改为所有来源。
代码:
CFArrayRef sources = ABAddressBookCopyArrayOfAllSources(addressBook);
CFIndex sourceCount = CFArrayGetCount(sources);
for (CFIndex i = 0; i < sourceCount; i++) {
ABRecordRef currentSource = CFArrayGetValueAtIndex(source, i);
int sourceType = [(__bridge NSNumber *)ABRecordCopyValue(currentSource, kABSourceTypeProperty) intValue];
switch (sourceType) {
case kABSourceTypeCardDAV:
NSLog(@"kABSourceTypeCardDAV");
break;
case kABSourceTypeCardDAVSearch:
NSLog(@"kABSourceTypeCardDAVSearch");
break;
case kABSourceTypeExchange:
NSLog(@"kABSourceTypeExchange");
break;
case kABSourceTypeExchangeGAL:
NSLog(@"kABSourceTypeExchangeGAL");
break;
case kABSourceTypeLDAP:
NSLog(@"kABSourceTypeLDAP");
break;
case kABSourceTypeLocal:
NSLog(@"kABSourceTypeLocal");
break;
case kABSourceTypeMobileMe:
NSLog(@"kABSourceTypeMobileMe");
break;
default:
break;
}
CFArrayRef allPeopleInSource = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, currentSource, kABPersonSortByLastName);
NSLog(@"Count of allPeopleInSource: %i", CFArrayGetCount(allPeopleInSource));
}
然后我得到了
kABSourceTypeCardDAV
Count of allPeopleInSource: 7
表示该来源中只有一个来源,只有7个记录。
但在我的地址簿中,我有79个联系人!
然后我犯了一个错误。我将sources
传递给ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering
,就像这样:
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, sources, kABPersonSortByLastName);
allPeople
中有多少成员?
72 !!!
完全没有sources
的记录数。
我将CFArrayRef传递给ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering
作为第二个参数,它需要一个ABRecordRef。如果我通过nil
怎么办?
最后,我得到了代码:
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, nil, kABPersonSortByLastName);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for (int i = 0; i < nPeople; i++) {
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
// more thing with `person`
}
现在,我可以在地址簿中找到所有联系人。
它适用于我的所有iDevices!
我对自己糟糕的英语感到非常抱歉......
希望这个答案可以帮到你。
注意 :现在我不完全理解AddressBook中的source
是什么,有人可以帮助我吗?
答案 2 :(得分:3)
@Jokinryou Tsui传递来源为nil是关键,谢谢!似乎源类型可能与Apple的此文档相对应: https://developer.apple.com/library/ios/documentation/AddressBook/Reference/ABSourceRef_iPhoneOS/#//apple_ref/doc/constant_group/Source_Types