How to check if the NSMutableArray already has (__bridge id) object in the array

631 views Asked by At

I am trying to add ABRecordRef item into my NSMutableArray. Just learned that It's needed to cast the C TypeDef into Objective-C id type using (_bridge id). So, before adding new items into the array, I want to check if the object is already in the array. Therefore, i tried using [nsmutablearray containsObject] but it does not seem to be working. Duplicate items still get added into the array. Do you know what could be wrong here?

-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person{
    if (![_buddiesList containsObject:(__bridge id)person]) {
        [_buddiesList addObject:(__bridge id)person];
        NSLog(@"Added");
    }
    return NO;
}
3

There are 3 answers

1
Fabian Kreiser On BEST ANSWER

There is no NS-equivalent to ABRecordRef and -containsObject: simply calls -isEqual: on all its objects to determine if there is a duplicate already included or not, so your approach can't work.

I suggest writing a wrapper class around ABRecordRef and implementing your own -isEqual: method there.

Update:
As pointed out by @omz, it does work, because CFEqual() is called, thanks! Using a wrapper class around ABRecordRef is still a good idea, though.

2
warrenm On

The reason your containsObject: call is failing to report the duplicate is that NSArray uses the NSObject method -isEqual: to determine equality, and CF types such as ABRecordRef do not have this method. We need to find a better way to determine equality.

The most efficient way to do this is to use an Objective-C wrapper around the AddressBook APIs, transforming each record into a bona fide NSObject instead of just bridge-casting it. Jim Dovey's iPhoneContacts project is a well-written solution for this. To build an equality testing method on top of this, just add an isEqual: method that uses the technique shown below for comparing the record IDs.

Alternatively, you can keep things as they are, but do a linear scan over the array each time you're about to add a record. Something like this:

BOOL foundMatch = NO;
for(id buddy in self.buddiesList)
{
    if(ABRecordGetRecordID(buddy) == ABRecordGetRecordID(person))
    {
        foundMatch = YES;
        break;
    }
}
0
MarioGT On

You can try cheking your array objects against isKindOfClass.

For instance:

if ([[buddiesList objectAtIndex:i] isKindOfClass: (_bridge id)person]) {

Do some stuff;

}