I want to create an array of ABRecordRef(s) to store contacts which have a valid birthday field.
NSMutableArray* bContacts = [[NSMutableArray alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
for( int i = 0 ; i < nPeople ; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i );
NSDate* birthdayDate = (NSDate*) ABRecordCopyValue(ref, kABPersonBirthdayProperty);
if (birthdayDate != nil){
[bContacts addObject:ref];
}
}
The compiler shows this warning:
warning: passing argument 1 of 'addObject:' discards qualifiers from pointer target type
I searched the web and found I have to cast ABRecordRef to a ABRecord* to be able to store in a NSMutableArray.
[bContacts addObject:(ABRecord*) ref];
But it seems ABRecord is not part of iOS frameworks. Now how I store ABRecordRef to NSMutableArray?
[bContacts addObject:(id) ref];
A ABRecordRef
is a typedef for CFTypeRef
and that in turn resolves to const void *
. And this is where the warning comes from: with the call to addObject:
, the const
qualifier is "lost".
In this case we know it's OK. A CFTypeRef is a semi-highlevel type, instances of this type support CFRetain
and CFRelease
. That in turn means it's probably OK to cast it to id
and treat it as a NSObject. So you should be simply able to do:
[bContacts addObject:(id)ref];
Create an NSObject wich store your ABRecordRef like this :
// ABContact.h
@interface ABContact : NSObject
{
ABRecordRef _record;
}
@property (nonatomic, readonly) NSDate *birthday;
- (id)initWithRecord:(ABRecordRef)aRecord;
@end
// ABContact.m
@implementation ABContact
#pragma mark - Init
- (id)initWithRecord:(ABRecordRef)aRecord;
{
if ((self = [super init]))
_record = CFRetain(aRecord);
return self;
}
#pragma mark - Getter
- (NSDate *)birthday
{
return (NSDate *)ABRecordCopyValue(record, kABPersonBirthdayProperty) autorelease];
}
#pragma mark - Memory management
- (void)dealloc
{
CFRelease(_record);
[super dealloc];
}
@end
You should take a look at the Erica Sadum library the author of the iPhone cookbook. Here is the code wich inspire this code -> url
I know this is an old question, but since the introduction of ARC, this is handled in a different way.
There are two possible ways of adding an ABRecordRef
to an NSMutableArray
now, both of which require a bridged cast:
Direct conversion
[bContacts addObject:(__bridge id)(ref)];
This simply converts the ABRecordRef
pointer, and should be used, if you didn't create ref
yourself using a method that has Create
in its name.
Transfer ownership to ARC
[bContacts addObject:CFBridgingRelease(ref)];
This converts the ABRecordRef
pointer, and in addition transfers its ownership to ARC. This should be used, if you used e.g. ABPersonCreate()
to create a new person.
More information can be found in the Transitioning to ARC Release Notes. There are also many other informative sources here on Stack Overflow, such as this question.