La gestione della memoria in iOS / ManagedObjectContext
-
11-10-2019 - |
Domanda
Sembra che io non ho capito la gestione della memoria in Objective C ... sigh.
Ho il codice seguente (si noti che nel mio caso, placemark.thoroughfare
e placemark.subThoroughfare
sono entrambi pieni di dati validi, quindi entrambe le if
-condizioni saranno TRUE
item
è legata ad una ManagedObjectContext
. Le variabili gestite in item
quali place
hanno setter / getter creati con @dynamic
. Così, la dichiarazione è
@property (nonatomic, retain) NSString *place;
@dynamic place;
Più tardi nel codice, nel ReverseGeocoderDelegate, accedo che:
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {
if (placemark.thoroughfare) {
[item.place release];
item.place = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];
} else {
[item.place release];
item.place = @"Unknown Place";
}
if (placemark.thoroughfare && placemark.subThoroughfare) {
// *** problem is here ***
[item.place release];
item.place = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}
Se non rilasciare item.place
alla posizione indicata nel codice, strumenti ci trova una perdita di memoria. Se lo faccio, il programma si blocca non appena provo ad accedere item.place
di fuori del metodo offendere.
Tutte le idee?
Soluzione
Prima di tutto, vorrei cambiare la logica in questo modo:
NSString *newPlace = nil;
if (placemark.thoroughfare && placemark.subThoroughfare) {
newPlace = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}
else {
if (placemark.thoroughfare) {
newPlace = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];
}
else {
newPlace = @"Unknown Place";
}
}
item.place = newPlace; // Either nil of valid string can be assigned to
Utilizzando immissione in puntatore semplicemente ri-inizializzazione non è così raccomandato da molti. Non dovete fare questo se fosse per risparmiare un po 'di memoria.
La logica precedente non rilasciando due volte . Ciò che fa di rilascio inizialmente è semplicemente decremento retainCount
. Se è 0, allora l'oggetto viene deallocato. L'oggetto non sarà deallocata fino alla sua retainCount
è 0.
Assumendo che il l'elemento ha la proprietà mantenere e dal stringa ritorna stringWithFormat:
autoreleased
, così, alla seconda uscita, si stava tentando di liberare quello che stava per essere autoreleased
comunque.
Il modo migliore per eliminare un oggetto più volte è semplicemente assegnando nil
ad esso.
Altri suggerimenti
Un punto di partenza potrebbe essere quello di ri-leggere di proprietà, perché non c'è bisogno di fare `[item.place rilasciare]' ovunque. Così è possibile rimuoverli. Il codice di dinamica creata dal runtime per consentire che la proprietà automaticamente maniglie rilasciando nulla precedentemente assegnato ad esso.
Inoltre, il [NSString stringWithFormat:...
crea un oggetto autorelease (non so se si sapeva che :-) Il che significa che se si dove gestire manualmente la memoria per una variabile (non una proprietà), allora si dovrà mantenere / rilasciarlo. Ma perché si sta utilizzando le proprietà, non è necessario.
Non riesco a capire perché gli strumenti è trovare una perdita di memoria. Forse un codice più in alto è a che fare con esso. Per esempio se si è andato item.place = [NSString alloc] initWith...];
allora penso che avrebbe bisogno di esso.
L'incidente ho il sospetto di essere a causa dei rilasci causando mantenere i conteggi pari a zero e innescando errori di accesso cattivi exec.
La speranza che aiuta.