ABAddressBookCopyArrayOfAllPeople and ABAddressBookGetPersonCount return different sizes

I have an application that sometimes crashes due to the array returned by ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering (), which has a different size in ABAddressBookGetPersonCount (). The code wrapper is shown below. Normally nPeople is the same size as the array. However, on a single iPhone user (or at least as reported by one user) nPeople is almost twice as large. I can stop the failure using the size of the array, not ABAddressBookGetPersonCount (). However, I'm not sure if this means that I don’t access all the contacts on the iPhone.

  • Has anyone encountered this problem before?
  • Why will the numbers be different?

I wondered if this is related to contacts stored in groups (I don’t know that there are groups - just an idea). Also, from the user's email address, I suspect that they are using MobileMe. I wondered if synchronization with MobileMe would create duplicates with another recordId, but not delete the existing Contact, at least not as far as ABAddressBookGetPersonCount ().

EDIT: I studied this a little more and have a good idea about the cause of the problem. Since I need a sorted array of contacts, I used ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering (). This requires an address book source β€” I used the default source. I believe that there can be different sources - a local source plus others, such as Exchange and MobileMe. Therefore, in my array there will be only local contacts, while the number returned by ABAddressBookGetPersonCount () will include all sources - hence, my failure. Therefore, I think it would be better to just work with local data in my application and use the array size returned by ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering rather than ABAddressBookGetPersonCount.

CFArrayRef allPeople = InSourceWithSortOrdering(addressBook, source, kABPersonSortByLastName); CFIndex nPeople = ABAddressBookGetPersonCount(addressBook); for (int i = 0; i < nPeople; i++) { ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i); } 
+6
source share
3 answers

ABAddressBookGetPersonCount And ABAddressBookCopyArrayOfAllPeople gives different arrays.

ABAddressBookGetPersonCount - Returns the number of person entries in the address book. ABAddressBookCopyArrayOfAllPeople - Returns all records of a person in the address book.

So, sometimes the same person may have additional records. That is why you can get different sizes.

+13
source

Today I meet this problem. My app also crashes in some special iDevices.

the code:

  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` } 

But he will sometimes fall. By adding some breakpoints, I found that allPeople count is less than nPeople .

By googling I found this article . I found that there might be something wrong with ABAddressBookCopyDefaultSource . Here I got the default source , I have to get all the sources .

the code:

 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)); } 

Then i got

  kABSourceTypeCardDAV Count of allPeopleInSource: 7 

which means that in this source there is only one source and only 7 records.

But in my address book I have 79 contacts!

Then I made a mistake. I passed sources to ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering , like this:

  CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, sources, kABPersonSortByLastName); 

How many members are allPeople ?

72 !!!

It is the number of records that are not in sources .

I passed CFArrayRef to ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering as the second parameter that ABRecordRef expects. What if i pass nil ?

Finally, I got the codes:

  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` } 

Now I can get all the contacts in my address book.

It works great on all my iDevices!

I'm sorry my bad english ...

Hope this answer helps you.

Note : now I do not understand what source in the address book, can someone help me?

+9
source

@Jokinryou Tsui Transmitting source as nil was the key, thanks! It seems that the source types might match this documentation from Apple: https://developer.apple.com/library/ios/documentation/AddressBook/Reference/ABSourceRef_iPhoneOS/#//apple_ref/doc/constant_group/Source_Types

+3
source

Source: https://habr.com/ru/post/897625/


All Articles