ABAddressBook和CFRelease的奇怪之处

时间:2013-01-09 17:11:45

标签: ios automatic-ref-counting abaddressbook

我在ABAddressBook上发生了一件奇怪的事情。这是一些代码:

- (NSArray*)addressBookArray {

    ABAddressBookRef addressBook = NULL;
    NSArray *temp = nil;

    if(&ABAddressBookCreateWithOptions != NULL) {

        CFErrorRef error = nil;
        addressBook = ABAddressBookCreateWithOptions(NULL, &error);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {

            dispatch_async(dispatch_get_main_queue(), ^{
                if(error) {
                    // handle error
                }
                else if(!granted) {
                    // handle not granted
                }
            });
        });
    }
    else { // iOS 5
        addressBook = ABAddressBookCreate();
    }
    if(addressBook) {
        temp = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
        CFRelease(addressBook);
    }
    return temp;
}

- (NSArray*)emailList {

    NSArray *temp = [self addressBookArray];
    NSMutableArray *list = nil;

    if(temp) {

        int n = temp.count;
        list = [NSMutableArray arrayWithCapacity:n];

        for(int i = 0; i < n ; i++) {

            ABRecordRef person = (__bridge ABRecordRef)[temp objectAtIndex:i];
            NSString *name = (__bridge_transfer NSString*)ABRecordCopyCompositeName(person);

            if(name) {
                ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);

                if(emails) {
                    int cnt = ABMultiValueGetCount(emails);

                    for(int j = 0; j < cnt; j++) {
                        NSString *email = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(emails, j);

                        if(email) {
                            [list addObject:email];
                            break;
                        }
                    }
                    CFRelease(emails);
                }
            }
        }
    }
    return list;
}

如果我致电emailList并注释掉CFRelease(addressBook),我会收到有关XCode Analyze可能泄漏的警告,但我的代码表现正常。

如果我取消注释CFRelease(addressBook),则没有泄漏警告,ABRecordRef personNSString *name具有正确的值,但如果总是为零则为ABMultiValueRef emails

混淆。

1 个答案:

答案 0 :(得分:2)

虽然我有些惊讶,但我怀疑ABPerson没有ABAddressBook没有完全定义。因此,地址簿需要存在与人一样长。鉴于此,只要这是全部单线程,您可能希望将ABAddressBook存储在ivar中,这样您就不必一直创建和销毁它。如果它是多线程的,请记住每个线程需要一个单独的ABAddressBook