Сбой при выпуске 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, и попытка получить к нему доступ приведет к сбою.