Как я могу добавить ABRecordRef в NSMutableArray в iPhone?

Я хочу создать массив ABRecordRef (s) для хранения контактов, у которых есть действительное поле рождения.

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

Компилятор показывает это предупреждение: предупреждение: передача аргумента 1 из 'addObject:' отбрасывает квалификаторы из целевого типа указателя Я искал в Интернете и обнаружил, что мне нужно отправить ABRecordRef в ABRecord *, чтобы иметь возможность хранить в NSMutableArray.

[bContacts addObject:(ABRecord*) ref];

Но, похоже, ABRecord не входит в рамки iOS. Теперь, как я сохраняю ABRecordRef в NSMutableArray?

Ответ 1

[bContacts addObject:(id) ref];

Ответ 2

A ABRecordRef является typedef для CFTypeRef и, в свою очередь, разрешается const void *. И здесь появляется предупреждение: при вызове addObject: отборочный const "потерян".

В этом случае мы это хорошо знаем. CFTypeRef - тип полувысотного уровня, экземпляры этого типа поддерживают CFRetain и CFRelease. Это, в свою очередь, означает, что, вероятно, ОК, чтобы передать его на id и рассматривать его как NSObject. Поэтому вы должны просто быть в состоянии:

[bContacts addObject:(id)ref];

Ответ 3

Создайте NSObject, который сохранит ваш ABRecordRef следующим образом:

// 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


Вы должны взглянуть на библиотеку Эрика Садум, автора кулинарной книги iPhone. Вот код, который вдохновляет этот код → url

Ответ 4

Я знаю, что это старый вопрос, но поскольку введение ARC, это обрабатывается по-другому.

Есть два возможных способа добавления ABRecordRef в NSMutableArray, оба из которых требуют мостового переноса:

Прямое преобразование

[bContacts addObject:(__bridge id)(ref)];

Это просто преобразует указатель ABRecordRef, и его следует использовать, если вы сами не создали ref, используя метод с Create в его имени.

Передача права собственности на ARC

[bContacts addObject:CFBridgingRelease(ref)];

Это преобразует указатель ABRecordRef и, кроме того, переносит его право собственности на ARC. Это следует использовать, если вы использовали, например, ABPersonCreate(), чтобы создать нового человека.

Более подробную информацию можно найти в Переход к заметкам о выпуске ARC. Здесь также есть много других источников информации о переполнении стека, например этот вопрос.