如何在iOS 7.1中对联系人进行排序

6

在Xcode 5.1的最新更新后,苹果提供的用于排序通讯录的示例代码已经失效。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);

但是现在,这段代码引发了一个警告

将较小的整数类型 'ABPersonSortOrdering'(也称为 'unsigned int')转换为 'void *'

在这一行中:

(void*) ABPersonGetSortOrdering())

我应该如何修改这段代码?

我实际上已经在苹果论坛、谷歌和stackoverflow上搜索了,但还是没有找到答案。

希望你能帮助我。

更新

看起来使用64位与这个警告有关。这与我的新iPhone 5s的包含一致。


我复制了您的代码,但是我并没有看到您提到的警告。不过,我应该指出您的创建方法已被弃用,而应该使用ABAddressBookCreateWithOptions()而不是ABAddressBookCreate。在访问地址簿之前,您还应该使用ABAddressBookRequestAccessWithCompletion检查是否有权限访问。 更多详情请参考这里... https://dev59.com/EGct5IYBdhLWcg3wc9Eg#12510649 - Sammio2
感谢您提到了弃用问题,但是我在这里粘贴的代码是从苹果的文档中提取的。在我的代码中,我使用ABAddressBookCreateWithOptions来创建地址簿。 - dequin
2个回答

20

正如您所述,问题出在新的64位架构上。对于32位架构,(void*)是一个32位指针,但对于64位架构,则是一个64位指针。函数ABPersonGetSortOrdering()返回的是ABPerson.h中被指定为uint32_t类型的ABPersonCompositeNameFormat值。因此,警告是在提醒您一个64位指针正在指向一个32位数字。

可以通过将返回值强制转换为unsigned long来消除该警告。这很完美,因为在64位架构上它将是64位,在32位架构上则是32位。

(void *)(unsigned long)ABPersonGetSortOrdering()
希望这可以帮助你!

1
如何看待 (void *)(NSUInteger)ABPersonGetSortOrdering()。我认为它可以在32位和64位编译环境下工作。 - TopChul

0

我怀疑你的问题与64位和32位架构之间的差异有关,Xcode 5.1默认启用了64位支持。如果指针是64位,而int是32位,则int太小无法容纳指针值。

您可以通过转到目标>构建设置来禁用应用程序的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,因为它们很可能更快,并且是一种更现代的做法。


老实说,我很惊讶这个API还没有为Foundation重新设计。肯定是时候了。 - erdekhayser
感谢您对64位的意见。您发布的代码与我拥有的代码没有区别,并且在“ABPersonComparePeopleByName”上也有相同的警告。 - dequin
它确实有所不同,它使用了非废弃的ABAddressBookRef构造函数,并确保用户事先授予了联系人访问权限,否则会导致当前应用程序崩溃,如果用户拒绝访问。此外,正如我所说,我的Xcode版本中没有关于你所说的那行代码的警告。 - Sammio2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接