0

我正在阅读通讯录中的联系人......一切都很顺利,直到我测试一个没有名字的联系人(因为我可以只用电子邮件、电话或 wathever 创建联系人......)。代码(简化)是这样的:

- (NSMutableArray *) getContactsInfo {
    NSMutableArray *contactsList = [[NSMutableArray alloc] init];
    localAddressBook = ABAddressBookCreate();

    int contactsLength = (int)ABAddressBookGetPersonCount(localAddressBook);

    if (contactsLength < 1)
        return nil;

    for(int currentContact=1; currentContact < (contactsLength + 1); currentContact++) {
        ABRecordRef person = ABAddressBookGetPersonWithRecordID(localAddressBook,(ABRecordID) currentContact);

        firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
        NSLog(@"%@", firstName);

        [contactsList addObject:firstName];
        CFRelease(person);
    }

    return contactsList;
}

我得到的输出是这样的:

2010-02-15 14:16:25.616 testApp[7065:207] Contact0
2010-02-15 14:16:25.618 testApp[7065:207] Contact1
2010-02-15 14:16:25.619 testApp[7065:207] Contact2
Program received signal:  “EXC_BAD_ACCESS”.

我有 3 个名字和姓氏的联系人,一个只用姓氏创建的,用于测试目的。

似乎我可以正确读取任何属性,例如电子邮件或带有数组的地址......但是当联系人缺少名字属性时,应用程序崩溃。

4

4 回答 4

4

您在代码中做了一些非常错误的事情:您假设记录 ID 是连续的并且从 1 开始。事实并非如此,您不能依赖这一点。

相反,您应该做的是使用ABAddressBookCopyArrayOfAllPeople查找地址簿中的所有记录,然后使用核心基础CFArray功能来获取各个项目。

(是的,iPhone 中的通讯录 API 很糟糕)

于 2010-02-15T23:18:48.470 回答
1

您可能希望启用 NSZombies以查看 EXEC_BAD_ACCESS 的确切来源。

于 2010-02-15T19:54:53.260 回答
0

为了确保崩溃发生在内部 ABRecordCopyValue而不是当您第一次尝试使用firstName时(可能是 NULL?)另外,person也不是 NULL,对吗?(一般来说,问题中的更多代码以及有关哪条线路崩溃的详细信息会有所帮助。)

要尝试的另一件事是强制person转换为 anABRecord*并使用[valueForProperty][1]; 这两种类型是免费桥接的,您可能会从后者中得到不同的结果(尽管我对此表示怀疑)。

更新:鉴于您发布的代码,您需要firstName在尝试通过它输出之前检查它不是 NULL NSLog- 很可能ABRecordCopyValue只是返回 NULL(表示该记录没有名字数据存在的事实。)您还应该检查personref 值本身的有效性 - 亲自传递 NULLABRecordCopyValue可能是其他问题的根源。

于 2010-02-15T19:35:27.097 回答
0

问题确实是 nil 名字 - 但不是在日志语句中,而是在您尝试将 nil 插入数组的位置。您不能将 nil 值插入到数组中,这会导致崩溃。NSLog 尚未将输出刷新到控制台,这就是为什么您还没有看到最后一条日志语句说名字是 nil。

每当您从通讯簿中获取数据时,请在将其插入任何内容之前检查该值是否为 nil。

于 2010-02-15T22:01:53.637 回答