Как сортировать контакты в iOS 7.1

После последнего обновления Xcode 5.1 перестал работать пример кода Apple для сортировки адресной книги. URL-адрес: https://developer.apple.com/library/ios/documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Chapters/DirectInteraction.html

Пример кода

ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFMutableArrayRef peopleMutable = CFArrayCreateMutableCopy(
                                          kCFAllocatorDefault,
                                          CFArrayGetCount(people),
                                          people
                                  );


CFArraySortValues(
        peopleMutable,
        CFRangeMake(0, CFArrayGetCount(peopleMutable)),
        (CFComparatorFunction) ABPersonComparePeopleByName,
        (void*) ABPersonGetSortOrdering()
);

CFRelease(addressBook);
CFRelease(people);
CFRelease(peopleMutable);

Но теперь этот код вызывает предупреждение

Cast to 'void *' from smaller integer type 'ABPersonSortOrdering' (aka 'unsigned int')

В этой строке

(void*) ABPersonGetSortOrdering())

Как мне изменить этот код?

На самом деле я просматривал форумы Apple, гуглил, переполнял Stackoverflow, но пока без радости.

Надеюсь, вы можете мне помочь.

ОБНОВЛЕНИЕ

Похоже, что использование 64-битной версии как-то связано с этим предупреждением. Это совпадает с включением моего нового iPhone 5s.


person dequin    schedule 17.03.2014    source источник
comment
Я продублировал ваш код и не получил упомянутого вами предупреждения, однако я должен указать, что ваш метод создания устарел и вместо ABAddressBookCreate вы должны использовать ABAddressBookCreateWithOptions(). Вы также должны заранее проверить, есть ли у вас разрешение на доступ к адресной книге с помощью ABAddressBookRequestAccessWithCompletion. См. здесь для получения более подробной информации... ="как мне правильно использовать метод aaddressbookcreatewithoptions в ios 6"> stackoverflow.com/questions/12083643/   -  person Sammio2    schedule 18.03.2014
comment
Спасибо за упоминание об устаревании, однако код, который я вставил сюда, был извлечен из документации Apple. В моем коде я использую ABAddressBookCreateWithOptions для создания адресной книги.   -  person dequin    schedule 19.03.2014


Ответы (2)


Как вы сказали, проблема связана с новой 64-битной архитектурой. (void*) — это 32-битный указатель для 32-битной архитектуры и 64-битный указатель для 64-битной архитектуры. Функция ABPersonGetSortOrdering() возвращает значение типа ABPersonCompositeNameFormat, которое указано как uint32_t в ABPerson.h. Таким образом, предупреждение сообщает вам, что 64-битный указатель указывает на 32-битное число.

Предупреждение можно устранить, приведя возвращаемое значение к типу unsigned long. Это идеально, потому что это будет 64 бита в 64-битной архитектуре и 32 бита в 32-битной архитектуре.

(void *)(unsigned long)ABPersonGetSortOrdering()

Надеюсь это поможет!

person Brent    schedule 19.03.2014
comment
Как насчет (void *)(NSUInteger)ABPersonGetSortOrdering(). Я думаю, что это будет работать в каждой 32-битной и 64-битной среде компиляции. - person TopChul; 26.08.2014

Я подозреваю, что ваша проблема связана с различиями между 64-битной и 32-битной архитектурой, Xcode 5.1 по умолчанию включил поддержку 64-битной версии. Если указатели имеют длину 64 бита, а целые числа — 32 бита, целое слишком мало для хранения значения указателя.

Вы можете отключить 64-битную компиляцию для своего приложения, перейдя в цель > настройки сборки, но я настоятельно рекомендую вам этого не делать. Кроме того, у меня работает следующий код, он также реализует новый метод создания и правильно реализует проверку авторизации (это гарантирует, что пользователь предоставил вашему приложению разрешение на доступ к контактам)

CFErrorRef * err;

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, err);

ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {

    if (!granted) {
        // No Access to address book, user has denied
        return;
    }

    CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFMutableArrayRef peopleMutable = CFArrayCreateMutableCopy(kCFAllocatorDefault,
                                                               CFArrayGetCount(people),
                                                               people);


    CFArraySortValues(peopleMutable,
                      CFRangeMake(0, CFArrayGetCount(peopleMutable)),
                      (CFComparatorFunction) ABPersonComparePeopleByName,
                      (void*) ABPersonGetSortOrdering());

    CFRelease(addressBook);
    CFRelease(people);
    CFRelease(peopleMutable);

});

Хотя, если бы я хотел быть очень придирчивым, я бы сказал, что вам, вероятно, следует преобразовать массив people в NSArray следующим образом:

NSArray *people = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);

Затем рассмотрите возможность реализации ваших методов сортировки с использованием NSSortDescriptors, так как они, вероятно, будут быстрее и, безусловно, более современным способом ведения дел.

person Sammio2    schedule 17.03.2014
comment
Честно говоря, я удивлен, что API не был переделан для Foundation. Определенно пора. - person erdekhayser; 18.03.2014
comment
Спасибо за ваш вклад в 64bit. Код, который вы публикуете, не отличается от того, что есть у меня, и в нем также есть такое же предупреждение на ABPersonComparePeopleByName - person dequin; 19.03.2014
comment
Это, безусловно, отличается. Он использует не устаревший конструктор для ABAddressBookRef и гарантирует, что пользователь заранее предоставил разрешение на доступ к контакту, что может привести к сбою вашего текущего приложения, если пользователь откажет в доступе. Кроме того, как я уже сказал, в моей версии xcode нет предупреждения для строки, о которой вы говорите. - person Sammio2; 20.03.2014