2010-04-10 9 views
5

Sono bloccato.L'indirizzo email di lettura dei contatti non riesce con strano problema di memoria

Sto cercando di ottenere un elenco di tutti gli indirizzi di posta elettronica di una persona. Sto usando il ABPeoplePickerNavigationController per selezionare la persona, che sembra tutto a posto. Sto impostando il mio

ABRecordRef personDealingWith; 

dall'argomento person a

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier { 

e tutto sembra che vada bene fino a questo punto. La prima volta che si esegue il codice seguente, tutto va bene. In seguito, posso ottenere problemi. Innanzitutto, il codice:

// following line seems to make the difference (issue 1) 
// NSLog(@"%d", ABMultiValueGetCount(ABRecordCopyValue(personDealingWith, kABPersonEmailProperty))); 

// construct array of emails 
ABMultiValueRef multi = ABRecordCopyValue(personDealingWith, kABPersonEmailProperty); 
CFIndex emailCount = ABMultiValueGetCount(multi); 

if (emailCount > 0) { 
    // collect all emails in array 
    for (CFIndex i = 0; i < emailCount; i++) { 
     CFStringRef emailRef = ABMultiValueCopyValueAtIndex(multi, i); 
     [emailArray addObject:(NSString *)emailRef]; 
     CFRelease(emailRef); 
    } 
} 

// following line also matters (issue 2) 
CFRelease(multi); 

Se compilato come scritto, non ci sono errori o problemi di analisi statica. Questo blocca con un errore di

*** -[Not A Type retain]: message sent to deallocated instance 0x4e9dc60

.

Ma aspetta, c'è di più! Posso sistemarlo in due modi.

In primo luogo, è possibile decommentare NSLog nella parte superiore della funzione. Ottengo una perdita da NSLog ABRecordCopyValue ogni volta, ma il codice sembra funzionare bene.

Inoltre, posso commentare la

CFRelease(multi); 

alla fine, che fa esattamente la stessa cosa. Errori di compilazione statici, ma codice in esecuzione.

Quindi, senza perdite, questa funzione si arresta in modo anomalo. Per evitare un crash, ho bisogno di emorragia della memoria. Né è una grande soluzione.

Qualcuno può indicare cosa sta succedendo?

risposta

13

Si è scoperto che non stavo memorizzando la variabile ABRecordRef personDealingWith correttamente. Non sono ancora sicuro di come farlo correttamente, ma invece di avere la funzionalità in un'altra routine (eseguita più tardi), ora sto facendo il lavoro da grugnito nel metodo delegate e utilizzando i risultati derivati ​​a mio piacimento. La nuova routine (di lavoro):

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { 
    // as soon as they select someone, return 
    personDealingWithFullName = (NSString *)ABRecordCopyCompositeName(person); 
    personDealingWithFirstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); 
    // construct array of emails 
    [personDealingWithEmails removeAllObjects]; 
    ABMutableMultiValueRef multi = ABRecordCopyValue(person, kABPersonEmailProperty); 
    if (ABMultiValueGetCount(multi) > 0) { 
     // collect all emails in array 
     for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) { 
      CFStringRef emailRef = ABMultiValueCopyValueAtIndex(multi, i); 
      [personDealingWithEmails addObject:(NSString *)emailRef]; 
      CFRelease(emailRef); 
     } 
    } 
    CFRelease(multi); 
    return NO; 
} 
0

Mi sono imbattuto in un problema simile. Il problema potrebbe risiedere a come si imposta il

ABRecordRef personDealingWith; 

Sembra che non si può semplicemente fare:

ABRecordRef personDealingWith = person; 

Perché personDealingWith rimane nullo. Invece quello che ho fatto è:

ABRecordID personID = ABRecordGetRecordID(person); 
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL); 
personDealingWith = ABAddressBookGetPersonWithRecordID(addressBook, personID); 
Problemi correlati