【问题标题】:How to read the Address Book as fast as other apps (like Viber, Whatsapp...)如何像其他应用程序(如 Viber、Whatsapp...)一样快速阅读通讯录
【发布时间】:2012-01-08 20:56:06
【问题描述】:

我正在编写一个应用程序,我需要读取地址簿数据以搜索一些感兴趣的联系人,这类似于现在许多应用程序(如 Viber、Whatsapp、Tango ......)。我需要进行匹配,因此我将数据发送到服务器并回复客户端,哪些联系人在他们的设备上安装了相同的应用程序。

这个idea的逻辑和机制我没有问题,我的问题是速度!我能够做我想做的事,但这个过程需要 27 秒才能在 iPhone4 上完成,上面有 500 个联系人。在同一台设备上,如果我们尝试 Viber 或 Whatsapp(或任何类似的应用程序),该过程只需不到 5 秒。

我的方法非常简单,我做一个 for 循环并阅读所有内容。我怎样才能像其他应用一样做同样的事情但速度更快?

这是我使用的代码:

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

    //sort the contents of the Mutable Array
    CFArraySortValues(peopleMutable, CFRangeMake(0, CFArrayGetCount(peopleMutable)), (CFComparatorFunction) ABPersonComparePeopleByName, (void*) ABPersonGetSortOrdering());

    //read the Address Book
    NSString *fullName, *number;
    ABRecordRef record = ABPersonCreate();
    ABMutableMultiValueRef multi;
    int contactID;
    int nameCount=0;//used to count the names in the string to send to server
    NSMutableString *strNamesToSend = [[NSMutableString alloc] init];

    for(CFIndex i=0; i< CFArrayGetCount(people); i++)
    {
        record = CFArrayGetValueAtIndex(people, i);
        multi = ABRecordCopyValue(record, kABPersonPhoneProperty);

        //Contact ID
        contactID = (int)ABRecordGetRecordID(record);

        //Full Name
        fullName = [NSString stringWithFormat:@"%@ %@", (NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty), (NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty)];
        fullName = [fullName stringByReplacingOccurrencesOfString:@" (null)" withString:@""];

        //fill data into AddressBook Table
        if(dbOpen == SQLITE_OK)
        {
            //pure sqlite3 work to save the names in my app
        }

        //Get multiple numbers from each user (if any)
        for(CFIndex j=0; j<ABMultiValueGetCount(multi); j++)
        {
            number = (NSString *)ABMultiValueCopyValueAtIndex(multi, j);

            nameCount++;

            //fill data into AllNumbers Table
            if(dbOpen == SQLITE_OK)
            {
                 //another sqlite3 work to save the numbers
            }
        }

        //send to the server every 29 numbers so we don't send all the 500 numbers at once
        if(nameCount > 29)
        {
            //send to server
        }

【问题讨论】:

  • 您是否对它进行了分析以查看这些时间都花在了哪里?您是否将数据同步发送到服务器?

标签: iphone ios client-server addressbook


【解决方案1】:

您是否尝试过分析您的代码?分析器应该能够快速识别代码的慢速部分。

通过非常简短的检查,我注意到您在每次迭代时都在计算数组大小,而不仅仅是一次。将其移出循环:

int count = CFArrayGetCount(people);
for (CFIndex i = 0; i < count; i++)

您没有详细说明您正在进行的 SQL 调用,但您正在检查 SQLITE_OK 的事实意味着您每次都在通过循环打开数据库。如果是这种情况,您应该将此调用移到循环之外,而不是每次都打开数据库。

我注意到nameCount没有被重置,这意味着一旦达到29,你的if case每次都会被命中,导致大量的网络请求。

【讨论】:

  • 我将尝试将计数移出数组并删除 SQLITE_OK 问题。变量 nameCount 正在重置,但为了尽量减少代码发布,我省略了这部分。它在最后一个 if 语句中被重置。我想我不明白什么是分析器。我会及时更新你所消耗的新时间,谢谢:)
  • 顺便说一下,我省略了数据库部分,因为它非常基础,但是如果您觉得需要它,我会发布它。
  • 回复。 “我不认为我理解什么是分析器”,它是 Instruments 提供的最强大的工具之一。尝试众多tutorials 之一以获取详细信息。这将向您展示代码的慢速部分。
  • 我会尝试教程并更新你。再次非常感谢您。
  • 哇,这真是一个强大的工具。我尝试了时间探查器,虽然我对探查器的东西不熟悉,但我看到有 5 或 6 个项目消耗了大量时间,并且都包含 sqlite3 一词!看来我做错的是将信息保存在 Documents 应用程序文件夹中,现在这让我了解到其他应用程序可能不存储这些信息(我将所有联系人的姓名和号码存储在地址簿)。真的@jnic 非常感谢这个提示,它可能会解决我的整个问题:) 我会在我的程序中进行更改并发布结果。
猜你喜欢
  • 2016-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 2010-12-18
  • 1970-01-01
相关资源
最近更新 更多