2

我有方法可以清除设备中的通讯录。方法如下。

-(void) clearAdressBook
{
    ABAddressBookRef addrBook=ABAddressBookCreate();
    CFArrayRef groups = ABAddressBookCopyArrayOfAllGroups(addrBook);
    if(groups)
    {
        CFIndex numGroups = CFArrayGetCount(groups);
        for(CFIndex idx=0; idx<numGroups; ++idx)
        {
            ABRecordRef groupItem = CFArrayGetValueAtIndex(groups, idx);

                CFArrayRef people=
                ABGroupCopyArrayOfAllMembers(groupItem);
                if(people)
                {
                    CFIndex peopleCount=CFArrayGetCount(people);
                    for(CFIndex ind=0;ind<peopleCount;++ind)
                    {
                        ABRecordRef person=CFArrayGetValueAtIndex(people, ind);
                        ABAddressBookRemoveRecord(addrBook, person, nil);
                        ABAddressBookSave(addrBook, NULL);
                        CFRelease(person);
                    }
                    CFRelease(people);//CRASH
                }

            }
        }

    CFRelease(groups);
}

当我发布 CFArrayRef 应用程序崩溃时,这里有什么问题?据我所知,我必须释放从 CF 方法返回的所有反对,其名称包含复制或创建权?

4

1 回答 1

5

您可能在这里过度释放了“人”对象。事实上人是从数组中检索的,它遵循“获取规则”,所以你不是它的所有者,你不能释放它(或者:如果你不确定对象,你可以先保留它然后释放它寿命)。在 for 循环结束时,当您释放“人”时,数组会尝试释放其内部对象(“人”),这些对象已过度释放,这会导致崩溃。

因此,请尝试删除 CFRelease(people) 语句,或者为了更加安全,在从数组中获取 person 后立即添加 CFRetain(people) (但不要删除 CFRelease(people) 指令)。

于 2013-05-10T12:41:46.897 回答