2014-03-30 76 views
0

,當我有這樣的代碼,列舉的地址簿中的聯繫人 -崩潰釋放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; 
} 

當我刪除釋放我不崩潰,但我想我會有泄漏。 任何想法可能是什麼原因?

感謝

+1

用戶產品 - >分析,你可能會得到一個很好的線索。 – jamihash

+0

謝謝,你是對的。看看我的答案 – shannoga

回答

0

嘛發現了這個問題,我相信這可以幫助其他用戶如此 -

貌似(__bridge_transfer NSString *)已經遞減CFStringRef的保留計數, 所以沒有必要將其釋放。

看起來這是沒有真正的用於__bridge

0

我還建議以檢查那些2個函數的結果:

ABAddressBookRef ADDRESSBOOK = ABAddressBookCreateWithOptions(NULL,&誤差); CFArrayRef addressBookPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);

這兩個中的任何一個都可以返回NULL,並試圖訪問它將導致崩潰。

0

你沒有顯示你的功能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); 
    }); 
}); 

我可以釋放的地址簿沒有任何問題