2009-09-09 11 views
17

Se utilizzo [UIImage imageWithCGImage:], passando in un CGImageRef, rilasciare il CGImageRef o UIImage si occupa di questo al momento della sua deallocazione?imageWithCGImage e memoria

La documentazione non è del tutto chiara. Dice "Questo metodo non memorizza nella cache l'oggetto immagine."

Originariamente ho chiamato CGImageRelease sul CGImageRef dopo aver superato a imageWithCGImage:, ma che ha causato un avvertimento malloc_error_break nel simulatore valere un doppio libera, si ebbero.

+2

Suggerisco di archiviare un bug di documentazione su https://bugreport.apple.com/ per chiedere loro di chiarirlo. –

risposta

0

Sono d'accordo con voi: la documentazione è confusa nella migliore delle ipotesi per questa API. Sulla base delle tue esperienze, quindi, concluderei che sei responsabile della vita di entrambi gli oggetti: lo UIImage e lo CGImageRef. Inoltre, è necessario assicurarsi che la durata dello CGImageRef sia almeno pari a quella dello UIImage (per ovvi motivi).

0

Stai utilizzando Xcode 3.1 su Snow Leopard? Sto vivendo lo stesso problema:

CGContextRef ctx = ...; 
CGImageRef cgImage = CGBitmapContextCreateImage(ctx); 
UIImage * newImage = [[UIImage imageWithCGImage:cgImage] retain]; 

CGImageRelease(cgImage); // this should be OK, but it now crashes in Simulator on SL 

Sto indovinando che l'aggiornamento a Xcode 3.2 risolverà il problema.

+0

A partire da Xcode 8.1, questo funziona per me. Se non rilascio il 'CGImage', ottengo una perdita di memoria, quindi presumo che questo sia il modo per farlo. – Aderis

4

Ho lo stesso problema in XCode 3.2.1 su Snow Leopard. Ho praticamente lo stesso codice di Jason.

ho guardato il codice di esempio iPhone che utilizza imageWithCGImage e hanno sempre rilasciare il CGImageRef utilizzando CGImageRelease dopo una chiamata a imageWithCGImage.

Quindi, si tratta di un errore nel simulatore? Ricevo sempre l'avviso malloc_error_break sulla console quando utilizzo CGImageRelease.

+0

Questo dovrebbe essere un commento sulla risposta di Jason, o una nuova domanda, in quanto SO non è un forum. – outis

+0

Non posso commentare i post degli altri perché non ho abbastanza "reputazione". Inoltre, questa non è una nuova domanda. Ho semplicemente suggerito che il problema potrebbe verificarsi solo nel simulatore ma non sul dispositivo. – Lextar

8

In base allo fundamental rule of Cocoa memory management, un oggetto proprietario deve rilasciare l'oggetto di proprietà quando non ne ha più bisogno. Altri oggetti sono responsabili per prendere e rilasciare la proprietà per conto proprio. Se un UIImage necessita di un oggetto per persistere ma non lo conserva o lo copia, si tratta di un bug nell'implementazione di UIImage e dovrebbe essere riportato come tale.

0

<> Non è la mia opinione. Ho avuto lo stesso problema. Secondo la documentazione

UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; 

imho mantiene tutti i riferimenti corretti. Se stai utilizzando un CGDataProvider, dai un'occhiata a CGDataProviderReleaseDataCallback e imposta un punto di interruzione nella richiamata. Puoi vedere che è correttamente chiamato dopo che hai [rilasciato] la tua immagine e puoi liberare() il tuo buffer di dati dell'immagine lì.

0

Non so se questo aiuta, ma ho avuto un problema simile. Ho letto le risposte e poi ha fatto la seguente, che sembra aver risolto:

CGImageRef cgImage = [asset thumbnail]; 
    UIImage *thumbImage = [[UIImage imageWithCGImage:cgImage ]retain]; 
    UIImageView *thumbImageView = [[UIImageView alloc] initWithImage:thumbImage]; 
    CGImageRelease(cgImage); 

ho usato l'autorelease come suggerito, ma non è stato sufficiente. Uno che avevo aggiunto l'immagine a UIImageView ho quindi rilasciato il cgImage.
Non si è schiantato e deallocato bene. Perché - Non ne ho idea ma ha funzionato.

La parte di anteprima delle risorse proviene dalla libreria ALsset, a tale proposito potrebbe essere necessario qualcos'altro.

+0

Sembra che stai perdendo thumbImage qui, a meno che non lo rilasci altrove. UIImageView.initWithImage: manterrà l'immagine. – fishinear

2

La proprietà in UIImage su CGImage non è chiara. Sembra non copiare lo CGImage ma non è garantito dalla documentazione. Quindi dobbiamo gestirlo da soli.

Ho utilizzato una nuova sottoclasse di UIImage per gestire questo problema. Basta conservare passando CGImage e rilasciandolo quando dealloc.

Ecco un esempio.

@interface EonilImage : UIImage 
{ 
    @private 
    CGImageRef  sourceImage; 
} 
- (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation; 

@end 



@implementation  EonilImage 

- (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation 
{ 
    self = [super initWithCGImage:imageRef scale:scale orientation:orientation]; 

    if (self) 
    { 
     sourceImage = imageRef; 
     CGImageRetain(imageRef); 
    } 

    return self; 
} 
- (void)dealloc 
{ 
    CGImageRelease(sourceImage); 
    [super dealloc]; 
} 
@end 

Perché il CGImage restituito dalla -[UIImage CGImage] proprietà non è garantito per essere lo stesso CGImage passato nel metodo init, i negozi di classe CGImage separatamente.

0
"This method does not cache the image object." 

Così l'UIImage prendere la proprietà, e quindi non si dovrebbe rilasciare il CGImageRef.