views:

562

answers:

1

I want to display an ABPeoplePicker with only people who have a geographic address defined.

So I create an addressBook and remove people that dont have an address:

addressBook = ABAddressBookCreate();
NSArray *peopleList = (NSArray *)ABAddressBookCopyArrayOfAllPeople( addressBook );
NSLog(@"There are %d people in addressBook", ABAddressBookGetPersonCount(addressBook));
for (id peopleRecord in peopleList) {
  ABMultiValueRef mv = ABRecordCopyValue((ABRecordRef)peopleRecord, kABPersonAddressProperty);
  CFIndex numberOfAddresses = ABMultiValueGetCount(mv);
  if( numberOfAddresses == 0 ) {
    CFErrorRef err;
    ABAddressBookRemoveRecord( addressBook, (ABRecordRef)peopleRecord, &err);
  }
}
[peopleList release];
NSLog(@"There are now %d people in addressBook", ABAddressBookGetPersonCount(addressBook));
ABPeoplePickerNavigationController *peoplePicker = [[ABPeoplePickerNavigationController alloc] init];
NSNumber* addressProp = [NSNumber numberWithInt:kABPersonAddressProperty];
[peoplePicker setAddressBook:addressBook];
peoplePicker.displayedProperties = [NSArray arrayWithObject:addressProp];
[peoplePicker setPeoplePickerDelegate:self];
[self presentModalViewController:peoplePicker animated:YES];

For info, before filtering I have 125 records, and after filtering I have 93 records.

When I display the peoplePicker and scroll through it, it crashes with:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (49) beyond bounds (49)'

Any idea what's wrong?

A: 

The fact that the NSRangeException's value is 49 (rather than some number between 93 and 125), I initially suspect that it's not directly related to this address book. Add a breakpoint for objc_exception_throw. That will cause you to drop into the debugger at the point of the exception, letting you see who's actually throwing it.

Rob Napier
It breaks in some private class: ABMembersController. So I suppose the addressBook when deleting records is corrupted: if I comment the line ABAddressBookRemoveRecord, it doesnt crash.
Stephan Burlot
I ran this code myself and I think you've found a Cocoa bug. I would first test this code against 3.0 and then open a radar. My experience with AddressBook on iPhone is that it isn't completely "cooked" yet. I don't think they've heavily tested in the case where you're displaying an addressbook that doesn't match the "real" addressbook. They seem to be doing some heavy work here in 3.0, because they've fixed some of the bugs we've reported, and then reintroduced them in later betas. You might create an empty address book that you add what you want into to see if that works around the bug.
Rob Napier
I couldnt find a way to create an empty address book. Did I miss something in the doc?
Stephan Burlot
No; I was probably confusing here. By "empty" I was suggesting "remove everything." It's a bit of a long-shot. I suspect the underlying problem is that ABPeoplePickerNavigationController isn't designed to work with uncommitted changes, and ABAddressBook isn't designed to be an arbitrary list of people, but just a staging ground for changes until you commit them. Even so, I'd open a radar. It seems a bug. And I'd double-check if there are difference in 3.0.
Rob Napier