как мога да добавя 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?


person Hadi Sharghi    schedule 20.05.2011    source източник


Отговори (3)


ABRecordRef е typedef за CFTypeRef и това от своя страна се преобразува в const void *. И оттук идва предупреждението: с извикването на addObject: квалификаторът const се "загубва".

В този случай знаем, че всичко е наред. CFTypeRef е тип от полувисоко ниво, екземплярите на този тип поддържат CFRetain и CFRelease. Това от своя страна означава, че вероятно е добре да го прехвърлите към id и да го третирате като NSObject. Така че трябва просто да можете да направите:

[bContacts addObject:(id)ref];
person DarkDust    schedule 20.05.2011

Създайте 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

person klefevre    schedule 20.05.2011

Знам, че това е стар въпрос, но след въвеждането на ARC, това се обработва по различен начин.

Има два възможни начина за добавяне на ABRecordRef към NSMutableArray сега, като и двата изискват мостово предаване:

Директно преобразуване

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

Това просто преобразува указателя ABRecordRef и трябва да се използва, ако не сте създали ref сами, използвайки метод, който има Create в името си.

Прехвърляне на собствеността на ARC

[bContacts addObject:CFBridgingRelease(ref)];

Това преобразува указателя ABRecordRef и в допълнение прехвърля собствеността му на ARC. Това трябва да се използва, ако сте използвали напр. ABPersonCreate() за създаване на нов човек.

Повече информация можете да намерите в Преминаване към ARC Бележки по изданието. Тук има и много други източници на информация в Stack Overflow, като този въпрос.

person Dennis    schedule 24.03.2015