2010-12-22 45 views
5

我有ABAddressBookGetPersonWithRecordID和ABPersonSetImageData一些内存泄漏。在发布之前,我一直在寻找解决方案,但我仍然不明白。如果我在iPhone 3GS上玩了很长时间,或者只与iPhone 3G接触很少,实际上应用程序会崩溃。这是我在didSelectRowAtIndexPath方法中的代码。我已经看过这些方法的示例代码,我没有看到我错过了什么。先谢谢你。 (对不起,错误......)内存泄漏与AddressBook框架

Contact *myContact = [fetchedResultsController objectAtIndexPath:indexPath]; 

cancelCreateContact = NO; 


ABAddressBookRef ab = ABAddressBookCreate(); 
int len = ABAddressBookGetPersonCount(ab); 
ABRecordID contactID; 
ABRecordRef person; 
BOOL alreadyExists = NO; 
CFStringRef first, last; 

for(int i = 1; i < (len + 1); i++) 
{ 
    person = ABAddressBookGetPersonWithRecordID(ab, (ABRecordID)i); 

    if(!person){ 
     len++; 
     continue; 
    } 

    first = ABRecordCopyValue(person, kABPersonFirstNameProperty); 
    last = ABRecordCopyValue(person, kABPersonLastNameProperty); 

    if ([[(NSString*)first lowercaseString] isEqualToString:[myContact.firstname lowercaseString]] && [[(NSString*)last lowercaseString] isEqualToString:[myContact.lastname lowercaseString]]) { 
     alreadyExists = YES; 
     contactID = ABRecordGetRecordID(person); 
     break; 
    } 
} 

if (alreadyExists) { 
    //NSLog(@"already exists"); 
    ABRecordRef aContactFound = ABAddressBookGetPersonWithRecordID(ab, contactID); 

    ABRecordRef aRecord = ABPersonCreate(); 

    CFErrorRef anError = NULL; 

    CFStringRef firstname = ABRecordCopyValue(aContactFound, kABPersonFirstNameProperty); 
    ABRecordSetValue(aRecord, kABPersonFirstNameProperty, firstname, &anError); 
    CFRelease(firstname); 

    CFStringRef lastname = ABRecordCopyValue(aContactFound, kABPersonLastNameProperty); 
    ABRecordSetValue(aRecord, kABPersonLastNameProperty, lastname, &anError); 
    CFRelease(lastname); 

    CFStringRef job = ABRecordCopyValue(aContactFound, kABPersonJobTitleProperty); 
    ABRecordSetValue(aRecord, kABPersonJobTitleProperty, job, &anError); 
    CFRelease(job); 

    ABMultiValueRef instantMessage = ABRecordCopyValue(aContactFound, kABPersonInstantMessageProperty); 
    ABRecordSetValue(aRecord, kABPersonInstantMessageProperty, instantMessage, &anError); 
    CFRelease(instantMessage); 

    ABMultiValueRef phone = ABRecordCopyValue(aContactFound, kABPersonPhoneProperty); 
    ABRecordSetValue(aRecord, kABPersonPhoneProperty, phone, &anError); 
    CFRelease(phone); 

    ABMultiValueRef email = ABRecordCopyValue(aContactFound, kABPersonEmailProperty); 
    ABRecordSetValue(aRecord, kABPersonEmailProperty, email, &anError); 
    CFRelease(email); 

    CFDataRef imageData = ABPersonCopyImageData(aContactFound); 
    ABPersonSetImageData(aRecord, imageData, &anError); 
    ABAddressBookSave(ab, &anError); 
    CFRelease(imageData); 

    ABUnknownPersonViewController *ABView = [[ABUnknownPersonViewController alloc] init]; 
    ABView.unknownPersonViewDelegate = self; 
    ABView.displayedPerson = aRecord; 
    ABView.allowsAddingToAddressBook = NO; 
    ABView.allowsActions = YES; 
    ABView.hidesBottomBarWhenPushed = YES; 

    [self.navigationController pushViewController:ABView animated:YES]; 

    [ABView release]; 

    CFRelease(aRecord); 

}else{ 
    //NSLog(@"doesn't exist"); 
    //sinon ouvre une fiche pré-remplie 

    ABRecordRef aRecord = ABPersonCreate(); 

    CFErrorRef anError = nil; 

    if(![myContact.firstname isEqualToString:@""]) ABRecordSetValue(aRecord, kABPersonFirstNameProperty, myContact.firstname, &anError); 

    if(![myContact.lastname isEqualToString:@""]) ABRecordSetValue(aRecord, kABPersonLastNameProperty, myContact.lastname, &anError); 

    if(![myContact.email isEqualToString:@""]) { 
     ABMultiValueRef ABemail = ABMultiValueCreateMutable(kABMultiStringPropertyType); 
     ABMultiValueAddValueAndLabel(ABemail, myContact.email, kABWorkLabel, NULL); 
     ABRecordSetValue(aRecord, kABPersonEmailProperty, ABemail, &anError); 
     CFRelease(ABemail); 
    } 

    if(![myContact.phone_business isEqualToString:@""] || ![myContact.phone_mobile isEqualToString:@""]){ 
     ABMultiValueRef ABphones = ABMultiValueCreateMutable(kABMultiStringPropertyType); 
     if(![myContact.phone_business isEqualToString:@""]) ([myContact.phone_business stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]].length == 4 || [myContact.phone_business stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]].length == 5) ? ABMultiValueAddValueAndLabel(ABphones, [NSString stringWithFormat:@"014443%@", myContact.phone_business], kABPersonPhoneMainLabel, NULL) : ABMultiValueAddValueAndLabel(ABphones, myContact.phone_business, kABPersonPhoneMainLabel, NULL); 
     if(![myContact.phone_mobile isEqualToString:@""] && ([myContact.phone_mobile stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]].length == 10)) ABMultiValueAddValueAndLabel(ABphones, myContact.phone_mobile, kABPersonPhoneMobileLabel, NULL); 
     ABRecordSetValue(aRecord, kABPersonPhoneProperty, ABphones, &anError); 
     CFRelease(ABphones); 
    } 

    if(![myContact.job isEqualToString:@""]) ABRecordSetValue(aRecord, kABPersonJobTitleProperty, myContact.job, &anError); 

    if(![myContact.msn isEqualToString:@""] || ![myContact.twitter isEqualToString:@""] || ![myContact.facebook isEqualToString:@""]){ 
     ABMultiValueRef ABmessaging = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType); 
     NSMutableDictionary *dMessaging; 

     if(![myContact.msn isEqualToString:@""]){ 
      dMessaging = [[NSMutableDictionary alloc] init]; 
      [dMessaging setObject:myContact.msn forKey:(NSString *) kABPersonInstantMessageUsernameKey]; 
      [dMessaging setObject:@"MSN" forKey:(NSString *)kABPersonInstantMessageServiceKey]; 
      ABMultiValueAddValueAndLabel(ABmessaging, dMessaging, kABPersonInstantMessageServiceMSN, NULL); 
      [dMessaging release]; 
     } 

     if(![myContact.twitter isEqualToString:@""]){ 
      dMessaging = [[NSMutableDictionary alloc] init]; 
      [dMessaging setObject:myContact.twitter forKey:(NSString *) kABPersonInstantMessageUsernameKey]; 
      [dMessaging setObject:@"Twitter" forKey:(NSString *)kABPersonInstantMessageServiceKey]; 
      ABMultiValueAddValueAndLabel(ABmessaging, dMessaging, kABOtherLabel, NULL); 
      [dMessaging release]; 
     } 

     if(![myContact.facebook isEqualToString:@""]){ 
      dMessaging = [[NSMutableDictionary alloc] init]; 
      [dMessaging setObject:myContact.facebook forKey:(NSString *) kABPersonInstantMessageUsernameKey]; 
      [dMessaging setObject:@"Facebook" forKey:(NSString *)kABPersonInstantMessageServiceKey]; 
      ABMultiValueAddValueAndLabel(ABmessaging, dMessaging, kABOtherLabel, NULL); 
      [dMessaging release]; 

     } 


     ABRecordSetValue(aRecord, kABPersonInstantMessageProperty, ABmessaging, &anError); 
     CFRelease(ABmessaging); 
    } 

    //pas dans l'XMLToObjectParser parce que ça prenait une plombe... 
    NSURL *url = [NSURL URLWithString:myContact.picture_path]; 
    NSData *data = [NSData dataWithContentsOfURL:url]; 

    if(!data){ 
     NSString *picture_path = (![myContact.gender isEqualToString:@""]) ? [NSString stringWithFormat:@"default_%@_head.png", [myContact.gender lowercaseString]] : @"default_m_head.png"; 

     [myContact setPicture_path:picture_path]; 
     NSError *error = nil; 
     if(![self.managedObjectContext save:&error]){ 
      NSLog(@"pb lors de l'enregistrement de picture path"); 
     } 

     //NSData *localData = [NSData dataWithContentsOfFile:myContact.picture_path]; 
     UIImage *image = [UIImage imageNamed:picture_path]; 
     NSData *localData = UIImagePNGRepresentation(image); 

     CFDataRef cfLocalData = CFDataCreate(NULL, [localData bytes], [localData length]); 
     ABPersonSetImageData(aRecord, cfLocalData, &anError); 
     ABAddressBookSave(ab, &anError); 
     CFRelease(cfLocalData); 

    }else { 
     UIImage *image = [UIImage imageWithData:data]; 
     NSString *extension = [(NSArray*)[myContact.picture_path componentsSeparatedByString:@"."] objectAtIndex:1]; 

     NSData *localData = ([extension isEqualToString:@"png"]) ? UIImagePNGRepresentation(image) : UIImageJPEGRepresentation(image, 1.0f); 

     CFDataRef cfLocalData = CFDataCreate(NULL, [localData bytes], [localData length]); 
     ABPersonSetImageData(aRecord, cfLocalData, &anError); 
     ABAddressBookSave(ab, &anError); 
     CFRelease(cfLocalData); 
    } 

    if (anError != nil) { NSLog(@"error :: %@", anError); } 



    ABUnknownPersonViewController *ABView = [[ABUnknownPersonViewController alloc] init]; 
    ABView.unknownPersonViewDelegate = self; 
    ABView.displayedPerson = aRecord; 
    ABView.allowsAddingToAddressBook = YES; 
    ABView.allowsActions = YES; 
    ABView.hidesBottomBarWhenPushed = YES; 

    [self.navigationController pushViewController:ABView animated:YES]; 


    [ABView release]; 

    CFRelease(aRecord); 

} 
CFRelease(ab); 

+0

“,实际上应用程序崩溃......”我们需要崩溃信息。这是一个不良的访问? – 2010-12-22 15:13:55

+0

这是一个exc_bad_access错误。我将在CFRelease – Najaaa 2010-12-22 15:49:59

回答

13

首先:读了您的Core Foundation的内存管理。你还不知道规则的核心。

其次:当CF友好功能的名称有“复制”,则必须检查其结果为NULL,并在做,如果它不是NULL释放的结果。所以这个:

first = ABRecordCopyValue(person, kABPersonFirstNameProperty); 

将成为内存泄漏,如果它永远其次CFRelease(first);

第三:如果一个核心基础值是NULL,将它传递给CFRelease将崩溃:

CFStringRef firstname = ABRecordCopyValue(aContactFound, kABPersonFirstNameProperty); 
ABRecordSetValue(aRecord, kABPersonFirstNameProperty, firstname, &anError); 
CFRelease(firstname); 

如果firstnameNULL(这可能是 - 想象一个名为只是“史密斯”联系)那么碰撞会发生