2010-12-22 10 views
5

मुझे ABAddressBookGetPersonWithRecordID और ABPersonSetImageData दोनों के साथ कुछ मेमोरी लीक मिल रही हैं। मैं यहां पोस्ट करने से पहले समाधान ढूंढ रहा हूं लेकिन मुझे अभी भी समझ में नहीं आ रहा है। अगर मैं आईफोन 3 जीएस के साथ काफी समय से खेलता हूं या आईफोन 3 जी के साथ केवल कुछ संपर्कों के साथ, वास्तव में एप्लिकेशन क्रैश हो जाता है। DidSelectRowAtIndexPath विधि में मेरा कोड यहां दिया गया है। मैंने इन विधियों के साथ नमूना कोड देखे हैं और मुझे नहीं लगता कि मैं क्या खो रहा हूं। पहले ही, आपका बहुत धन्यवाद। (गलतियों के लिए माफी चाहता ...)पता पुस्तिका ढांचे के साथ मेमोरी लीक

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

", वास्तव में एप्लिकेशन क्रैश हो जाता है ..." हमें क्रैश जानकारी की आवश्यकता है। क्या यह एक खराब पहुंच है? –

+0

यह एक exc_bad_access त्रुटि है। मैं यह जांचने जा रहा हूं कि CFRelease – Najaaa

उत्तर

13

सबसे पहले: अपने कोर फाउंडेशन स्मृति प्रबंधन के बारे में पढ़ें। आप अभी तक दिल से नियमों को नहीं जानते हैं।

दूसरी बात: जब एक CF के अनुकूल समारोह के नाम पर "कॉपी" है, तो आपको NULL के लिए अपने परिणाम की जांच करना चाहिए, और है कि परिणाम जारी हो जाने पर अगर यह NULL नहीं है। तो यह:

first = ABRecordCopyValue(person, kABPersonFirstNameProperty); 

एक स्मृति रिसाव हो जाएगा अगर यह CFRelease(first); द्वारा पीछा कभी नहीं रहा है।

तीसरा: अगर एक कोर फाउंडेशन मूल्य, NULL है यह CFRelease को गुजर दुर्घटना होगा:

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

तो firstname है NULL (यह हो सकता है जो - बस "स्मिथ" नामक एक संपर्क की कल्पना) फिर एक क्रैश होगा।

+0

से पहले मान पूर्ण नहीं हैं यह एक exc_bad_access त्रुटि थी। मैंने कोर फाउंडेशन मेमोरी मैनेजमेंट पढ़ा और पहले और आखिरी के लिए सीएफआरईलीज जोड़ा लेकिन यह क्रैश हो गया, इसलिए मैंने हटा दिया लेकिन आप पूरी तरह से सही हैं कुछ संपर्कों को अंतिम नाम या प्रथम नाम नहीं मिला, इसलिए यह तार्किक था ... इंस्ट्रूमेंट्स ने ABAddressBookGetPersonWithRecordID के साथ लाइन की ओर इशारा किया लेकिन शायद यह वास्तव में विश्वसनीय नहीं है। मैं इसे तुरंत बदलने जा रहा हूं, धन्यवाद – Najaaa

+0

** हमेशा ** एक सही परिणाम होने पर यह निर्धारित करने के लिए 'अगर (...)' परीक्षण के साथ अपनी गेट/कॉपी/कॉल बनाएं का पालन करें। इनमें से कोई भी एपीआई 'न्यूल' वापस कर सकता है। –

+0

मुझे अब ABAddressBookGetPersonWithRecordID के साथ मेमोरी लीक नहीं है, धन्यवाद। मुझे लगता है कि मेरे पास अभी भी समस्या है ABPersonSetImageData छवि प्रारूप के कारण है जो मैं निर्दिष्ट नहीं करता (थंबनेल, आदि) – Najaaa