Сбой при выпуске ABAddressBookRef

У меня есть этот код, который перечисляет контакты адресной книги -

  +(void)enumerateAddressBookContacts:(void(^)(NSString *name, NSArray *phoneNumbers, NSArray *emailAddresses, NSData *imageData, NSString *recordId))enumerationBlock  failure:(void (^)( NSError *error))failure{

    [self requestAddressBookPermissionsWithCompletion:^{
    if (enumerationBlock)
    {
        CFErrorRef error = nil;
        ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
        CFArrayRef addressBookPeople = ABAddressBookCopyArrayOfAllPeople (addressBook);
        NSArray* people = (__bridge NSArray*)addressBookPeople;

        if ([people count])
        {

            for (NSUInteger i = 0; i < [people count]; i++)
            {
                ABRecordRef person = (__bridge ABRecordRef)people[i];

                NSArray *phoneNumbers = [self phoneNumbersOfPerson:person];
                NSArray *emailAddresses = [self emailAddressesOfPerson:person];
                NSString *fullName = [self fullNameOfPerson:person];
                NSData *imageData = [self imageDataOfPerson:person];
                NSString *recordId = [NSString stringWithFormat:@"%d", ABRecordGetRecordID(person)];

                void (^block)(NSString*, NSArray *, NSArray *, NSData*, NSString*) = [enumerationBlock copy];
                block(fullName,phoneNumbers,emailAddresses,imageData,recordId);

            }
        }
        else
        {
            //No contacts in addressbook
            if (failure) {
                NSError *error = [NSError errorWithDomain:kAddressBook code:kAddressBookUploadFailReasonEmptyAddressBook userInfo:@{NSLocalizedDescriptionKey:kAddressBookUploadFailReason[kAddressBookUploadFailReasonEmptyAddressBook]}];
                failure(error);
            }
        }

          if (addressBookPeople)
         {
             CFRelease(addressBookPeople);
         }

         if (addressBook)
         {
             CFRelease (addressBook);
        }
    }

} failure:^(NSError *error) {
    if (failure) {
        failure(error);
    }   
}];
}

У меня сбой при выпуске ABAddressBookRef объект в конце метода.

Это пример одного из методов перечисления (все они действуют одинаково) -

+ (NSArray*)phoneNumbersOfPerson:(ABRecordRef)person
{
    ABMutableMultiValueRef phones = ABRecordCopyValue (person, kABPersonPhoneProperty);
    NSMutableArray *phoneNumbers = [NSMutableArray array];
    CFIndex phonesNumberCount = ABMultiValueGetCount (phones);
    if (phonesNumberCount > 0)
    {
        for (CFIndex index = 0; index < phonesNumberCount; index++)
        {
            CFStringRef phoneValue = ABMultiValueCopyValueAtIndex (phones, index);
            [phoneNumbers addObject:(__bridge_transfer NSString *)phoneValue];

            if (phoneValue)
            {
                CFRelease (phoneValue);
            }
        }
    }

    if (phones)
    {
        CFRelease (phones);
    }

    return phoneNumbers;
}

Когда я удаляю релиз, я не падаю, но предполагаю, что у меня будет утечка. Есть идеи, в чем может быть причина?

Спасибо

3 ответа

Хорошо нашли проблему, и я верю, что она может помочь другим пользователям, так -

Похоже (__bridge_transfer NSString *) уже уменьшает счет удержания CFStringRefТаким образом, нет необходимости выпускать его.

Похоже, это не так для __bridge

Вы не показываете, что делает ваша функция requestAddressBookPermissionsWithCompletion. Я вставлю часть кода, который я использую, в мой менеджер адресной книги:

//Saving current thread queue.
dispatch_queue_t currentQueue = dispatch_get_global_queue(0,0);
CFErrorRef error = nil;
addressBook = ABAddressBookCreateWithOptions(NULL,&error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
    // callback can occur in background, address book must be accessed on thread it was created on
    dispatch_async(currentQueue, ^{
        if(error || !granted){

            //SOME ERROR HAPPENED OR USER DIDN'T ALLOW ACCESSING CONTACTS -> SHOW SOME FEEDBACK
        }
        else {
            // DO WHATEVER YOU NEED WITH THE ADDRESSBOOK

        }
        CFRelease(addressBook);
    });
});

Я могу выпустить адресную книгу без проблем

Я также предложил бы проверить результат для этих двух функций:

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions (NULL, & error); CFArrayRef addressBookPeople = ABAddressBookCopyArrayOfAllPeople (addressBook);

Любой из этих двух может вернуть NULL, и попытка получить к нему доступ приведет к сбою.

Другие вопросы по тегам