iOS使用ARC发布Reference iPhoneContactList

时间:2013-12-18 21:44:18

标签: ios objective-c automatic-ref-counting

在我的应用程序中,我从设备中获取联系人列表, 这一切都按计划进行,直到我到达释放线。

应用程序根据需要进行编译,但在运行时它只是停止,指向发布行并告诉绿灯点亮的文本访问不良。

这是我的代码: 在我自己的队列中使用GCD调用的函数(因为这是我在后台进行的一个重要过程,我不确定是否必须使用@autoreleasepool

我运行了product-> analyze,这里有一些函数我添加了注释。

-(void)getContacts
{
@autoreleasepool {
ABAddressBookRef iPhoneAddressBook = ABAddressBookCreateWithOptions(NULL, NULL);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    ABAddressBookRequestAccessWithCompletion(iPhoneAddressBook, ^(bool granted, CFErrorRef error)
    {
        accessGranted = granted;
        dispatch_semaphore_signal(sema);
    });
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else { // we're on iOS 5 or older
    accessGranted = YES;
}
if (accessGranted)
{
    CFErrorRef error = nil;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); // indirection
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
    NSMutableArray* EmailArrayPerPerson = [[NSMutableArray alloc]init];//value stored to EMailArrayPerPerson during its initialization is never read
    NSMutableArray* PhoneArrayPerPerson = [[NSMutableArray alloc]init];//value stored to PhoneArrayPerPerson during its initialization is never read
    for (int i = 0; i < ABAddressBookGetPersonCount(addressBook); i++)//potential leak of an object stored in to contact
    {
        NSMutableDictionary *ContactsDetails = [NSMutableDictionary dictionary];
        ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
        NSString *contact = (__bridge NSString *)(ABRecordCopyCompositeName(ref));
        if([contact length] <=0)
            continue;
        ContactsDetails = [NSMutableDictionary dictionary];
        [ContactsDetails setObject:contact forKey:@"CName"];
        ABMultiValueRef emails = ABRecordCopyValue(ref, kABPersonEmailProperty);
        EmailArrayPerPerson = [[NSMutableArray alloc]init];

        NSLog(@"dictionary is:%@",[ContactsDetails objectForKey:@"CName"]);
        for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++)
        {
            NSString* email = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(emails, j));
            [EmailArrayPerPerson addObject:email];
        }
        [ContactsDetails  setObject:EmailArrayPerPerson forKey:@"CEMails"];//potential leak in emails
        ABMultiValueRef multi = ABRecordCopyValue(ref, kABPersonPhoneProperty);
        PhoneArrayPerPerson = [[NSMutableArray alloc]init];
        for (CFIndex j=0; j < ABMultiValueGetCount(multi); j++)
        {
            NSString* phone = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(multi, j));
            [PhoneArrayPerPerson addObject:phone];
        }
         [ContactsDetails setObject:PhoneArrayPerPerson forKey:@"CPhones"];
         [Contacts addObject:ContactsDetails];
          CFRelease(ref);//incorect decrement of the reference count of an object that is not owned at this point by the caller.
          CFRelease(multi);
    }
    CFRelease(allPeople);//Potential leak of an object stored in to addressBook
   // CFRelease(addressBook);// *strange issue with bad access is here* 
}
else
{
    CFRelease(iPhoneAddressBook);
    return;
}
}
}

我知道这是一个很大的功能,但我认为我必须按原样添加它以使一切都清楚。 我对iOS SDK很陌生,所以请你能解释一下那里发生的不良访问情况吗?

我不确定,但我认为addressBook是冗余分配,因为我已经分配iPhoneAddressBook我不确定。

(我也不确定是否必须发布它(因为我正在使用ARC,但ARC不应该为我释放crefs)。

1 个答案:

答案 0 :(得分:2)

主要问题似乎在这里:

ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
// ...
CFRelease(ref);  // <-- WRONG

CFArrayGetValueAtIndex()在其名称中没有“创建”或“复制”,因此您 不要“拥有”返回的对象,不得释放它。 有关详细信息,请参阅“适用于Core Foundation的内存管理编程指南”中的"Ownership Policy"

要解决contact的潜在泄漏,请替换

NSString *contact = (__bridge NSString *)(ABRecordCopyCompositeName(ref));

通过

NSString *contact = (__bridge_transfer NSString *)(ABRecordCopyCompositeName(ref));

ABRecordCopyCompositeName() 在其名称中有“复制”,因此您拥有了返回的对象。 __brigde_transfer将所有权“转移”到ARC,以便对象为 contact超出范围时发布。