ABRecordCopyValue可以返回什么?(解决bad access问题)

3
我使用这个简单的代码来获取iOS 7通讯录中的所有联系人。我的地址簿中有155个联系人。当我记录人们的名字时,我会从我的地址簿中随机地获得34个正确的名字,15个名字为空,然后在第50个项目上发生了一个错误的访问崩溃,在该行出错。
   NSString *firstNames = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty)

我尝试记录姓氏或图片,但没有任何变化。我尝试避免在空对象上执行ABRecordCopyValue,但是仍然没有变化。我尝试在50项以上执行ABRecordCopyValue,并且从50到150的项目结果相同。我做错了什么?除正确值和null之外,ABRecordCopyValue还能返回什么?

+(NSArray *)getAllContactsAddress
{
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

// SUPPOSE access has been granted
BOOL accessGranted = true;

if (accessGranted) {
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
    ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName);
    CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
    NSMutableArray* items = [NSMutableArray arrayWithCapacity:nPeople];


    for (int i = 0; i < nPeople; i++)
    {
        ContactsData *contacts = [ContactsData new];

        ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);

        NSString *firstNames = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);

        NSLog(@"%@",firstNames);
    }
}

抱歉,我的错误。原本应该是nPeople而不是-1。 - Sasha Grievus
那么它在哪里崩溃了?你能提供一个堆栈跟踪吗? - trojanfoe
抱歉,我不知道如何发布堆栈跟踪 ^^ 但是当执行ABRecordCopyValue(person,kABPersonFirstNameProperty)时,它会崩溃,就像我在问题文本中所说的那样,这发生在人员编号(i)50上(似乎没有任何明显的原因)。 - Sasha Grievus
1
当程序崩溃时,person == NULL 吗? - trojanfoe
尝试过了,好像没问题。当它工作时(前34项),人是“CPRecord: 0x17db5b10 ABPerson>”(数字会变)。然后在第15项处为null(仍在工作但名称为空),然后在第50项处变成“__NSCFType”,并崩溃了。 - Sasha Grievus
1个回答

5

我认为问题在于nPeople的值错误,与您假设的所有人数不匹配。您使用了一种奇怪的方法来获取nPeople,而CFArray已经提供了一个简单明了的方法。

我想这个解决方案会起作用:

CFIndex nPeople = CFArrayGetCount(allPeople);

在使用 person 变量之前,你需要检查其是否为非 NULL 值:

ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
NSAssert(person, @"Non-person detected!");

是的,这是正确的(谢谢,它正在工作),但我仍然有一个问题:为什么我只得到了34个联系人而不是155个?所以问题在于ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering没有像它应该做的那样真正获取所有的联系人吗? - Sasha Grievus
1
@ElisabettaFalivene 这可能是因为您要求通讯录按名字的首字母排序返回条目?也许可以使用其他方法?另外,如果我提供了一些帮助,给个赞怎么样? - trojanfoe
对我来说仍然不是很清楚,但是使用ABAddressBookCopyArrayOfAllPeople而不是ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering解决了问题。在第二种情况下,函数返回地址簿中的子集,而不是全部。谢谢你的帮助! - Sasha Grievus
通讯录是从多个来源(如Facebook、iCloud等)编制的记录集合。默认来源是输入到联系人中的地址,而不是从其他来源(如交换服务器)同步的地址。因此,如果您有155个联系人,但其中121个是从交换服务器同步的,那么如果您从默认来源检索联系人,您只会收到34个联系人。如果您想获取每个联系人,无论其来源如何,“ABAddressBookCopyArrayOfAllPeople”是正确的方法。 - alivingston

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