Domanda

Simile al noto problema di perdita di memoria relativo alla creazione e alla distruzione di un'istanza di UIImagePickerController, sto riscontrando problemi simili relativi alle istanze della classe UIViewController. Il modo consigliato di utilizzare UIImagePickerController è quello di creare l'istanza una volta e tenerla in circolazione per tutta la durata dell'applicazione, anche se ciò utilizzerà la memoria che potrebbe essere necessaria altrove.

La situazione con cui ho a che fare riguarda 2 istanze della classe UIViewController. All'avvio, viene creata la prima istanza e la sua vista viene aggiunta a un'altra "principale" Classe UIViewController che fa parte di MainWindow.xib. In questa prima istanza è presente un " info " pulsante che, quando toccato, passa a una nuova istanza della classe UIViewController (se non è già stata creata). Il "principale" UIViewController gestisce questa commutazione con la solita animazione a fogli mobili. La configurazione di base è visibile nello "Inizio dello sviluppo di iPhone: esplorazione dell'SDK per iPhone" libro di Dave Mark.

Il problema che si presenta è che una volta che " info " il pulsante viene toccato la prima volta, la memoria viene allocata alla nuova seconda istanza di UIViewController e non viene rilasciata fino al termine dell'applicazione. A causa del numero di elementi in questa vista informazioni, una volta istanziata utilizza circa 1 MB di memoria e la sua vista viene aggiunta alla superview. Qualsiasi tentativo di distruggere e ricreare costantemente questa istanza provoca una perdita di memoria, simile a quella esistente se si tenta di fare la stessa cosa con le istanze della classe UIImagePickerController. Sospetto che la causa principale sia la stessa tra le due classi.

Il nocciolo del mio problema è la necessità di liberare quanta memoria prima di consentire all'utente di scattare una foto con la fotocamera. Tuttavia, una volta che l'utente ha scattato una foto e ha visto l'immagine risultante per la prima volta, è consentito toccare le "informazioni". pulsante che esiste sulla prima istanza di UIViewController. Una volta toccato, il " principale " UIViewController rimuove la vista UIViewController esistente e la sostituisce con quella per la schermata delle informazioni. La schermata delle informazioni ha un " back " per tornare indietro. Tuttavia, una volta che l'utente lascia la schermata informativa e sceglie di scattare un'altra foto con la fotocamera, la memoria allocata alla schermata informativa rimane in memoria.

La classe UIImagePickerController utilizza temporaneamente circa 15-18 MB mentre elabora l'immagine da 2 megapixel prima di rilasciare i suoi riferimenti interni e "imagePickerController: didFinishPickingImage " viene chiamato un delegato. Sto riscontrando avvisi di memoria insufficiente una volta che la seconda istanza di UIViewController è stata creata tramite il pulsante info e quindi l'utente ha scelto di scattare un'altra foto.

Tecnicamente la memoria non perde se scatti foto più e più volte con o senza toccare il pulsante informazioni nel mio caso, ma a causa di altri problemi relativi ai processi in background su iPhone (Safari, ecc.) che sono al di fuori del tuo controllo, DEVI liberare quanta più memoria possibile mentre lavori con cose come la fotocamera.

Qualche consiglio su come creare e distruggere in modo pulito istanze della classe UIViewController in modo tale che la memoria non vada a vuoto?

È stato utile?

Soluzione

Stai caricando il controller della seconda vista da un NIB? In tal caso, ti consigliamo di verificare che stai rilasciando correttamente la memoria associata.

Ecco come appare un tipico controller di visualizzazione basato su NIB nei miei progetti.

SomeViewController.h

@interface SomeViewController : UIViewController {
    UILabel *someLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *someLabel;

@end

SomeViewController.m

@implementation SomeViewController

@synthesize someLabel;

- (void)dealloc {
    // Release our retained IBOutlets
    self.someLabel = nil;
    [super dealloc];
}

@end

Altri suggerimenti

Un modo per ridurre l'utilizzo della memoria sarebbe ridimensionare l'immagine a qualunque dimensione tu voglia (a meno che ovviamente tu non voglia un'immagine 320x480). Ciò ha aiutato molto nel mio caso.

Il secondo viewcontroller di cui stai parlando cambia? In caso contrario, sarebbe meglio renderlo un singleton e utilizzare la stessa istanza. È possibile modificare in qualsiasi momento i valori utilizzati dal viewcontroller. Questo articolo spiega come creare oggetti singleton ( con il codice)

Un altro articolo qui mostra l'uso di una classe singleton (anche se diversa da il tuo caso d'uso, chiarirà come usare i singoli)

Suggerirei di creare un oggetto singleton anche per UIImagePickerController.

Hai dei cicli nella tua catena di proprietà? Qualcosa del tipo:

@interface FirstViewController: UIViewController {
  SecondViewController *secondViewController;
}
@end

@interface SecondViewController: UIViewController {
  FirstViewController *firstViewController;
}
@end

Se non interrompi esplicitamente questo ciclo quando scarti questi controller di visualizzazione, si verificheranno delle perdite.

Inoltre, credo che tu sia responsabile del rilascio di tutti gli oggetti di livello superiore caricati da un file pennino quando non sono più necessari.

Forse potresti salvare l'immagine prima di passare alla visualizzazione informazioni. Dopo aver salvato, rilascia l'immagine e poi passa alla visualizzazione informazioni. Se l'utente torna indietro, carica l'immagine dalla cartella.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top