2012-10-06 12 views
5

Sto provando un test semplice per un progetto molto più complesso, ma sono sconcertato sul motivo per cui il codice riportato di seguito si arresta e genera un errore EXC_BAD_ACCESS?UIImage from CGImageRef

Questo è chiamato da un UIView.

- (void)testing { 
     NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"ball.png" ofType:nil]; 
     CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage]; 
// CGImageRetain(imageRef); 

     UIImage *newImage = [[UIImage alloc]initWithCGImage:imageRef]; 
     UIImageView *iv = [[UIImageView alloc]initWithImage:newImage]; 
     [self addSubview:iv]; 
} 

La mia ipotesi è che il CGImageRef non viene mantenuto, ma l'aggiunta di CGImageRetain (imageRef); non fa differenza.

Vorrei anche notare che questo progetto ha attivato ARC.

EDIT

ho fatto un po 'di più test' e hanno scoperto che questa è direttamente correlata alla ARC, come ho creato 2 progetti di base tra cui solo il codice di cui sopra. Il primo con ARC si è spento e ha funzionato perfettamente. Il prossimo con ARC attivato e BAM si interrompe con lo stesso errore. La cosa interessante è che ho ricevuto un errore di log SOLO la prima volta che ho eseguito il progetto prima del crash.

Error: ImageIO: ImageProviderCopyImageBlockSetCallback 'ImageProviderCopyImageBlockSetCallback' header is not a CFDictionary... 

risposta

9

Questa linea è il problema:

CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage]; 

Il creato UIImage sarà rilasciato immediatamente dopo questo pieno espressione (ad esempio dopo questa riga). Quindi, anche il tentativo di aggiungere uno CGImageRetain() in seguito non funzionerà.

Il problema fondamentale è la CGImageRef tornato da CGImage è quasi certamente un Ivar del UIImage e verrà rilasciato quando il UIImage è deallocted.

Il modo generico per risolvere questo problema è estendere la durata dello UIImage. È possibile eseguire questa operazione inserendo il UIImage in una variabile locale e facendolo riferimento dopo l'ultimo riferimento allo CGImage (ad esempio con (void)uiimageVar). In alternativa, è possibile mantenere la CGImageRef su quella stessa linea, come in

CGImageRef imageRef = CGImageRetain([[[UIImage alloc] initWithContentsOfFile:imagePath] CGImage]); 

Ma se si esegue questa operazione, non dimenticate di rilasciare il imageRef quando hai finito.

5

è stato scritto da:

CGImageRef imageRef = [[[UIImage alloc]initWithContentsOfFile:imagePath]CGImage]; 

Quella linea crea un UIImage, ottiene la sua proprietà CGImage, e poi rilascia l'oggetto UIImage. Poiché non stai mantenendo lo CGImage su quella linea, l'unico proprietario dello CGImage è lo UIImage. Quindi, quando lo UIImage viene rilasciato e immediatamente deallocato, rilascia anche lo CGImage.

È necessario conservare CGImage prima che venga rilasciato lo UIImage. Prova questo:

CGImageRef imageRef = CGImageRetain([[UIImage alloc]initWithContentsOfFile:imagePath].CGImage); 

e quindi alla fine della funzione:

CGImageRelease(imageRef); 
+0

Fantastico, ora vedo esattamente cosa sta succedendo. Almeno ero sulla strada giusta. Grazie Rob. – EcksMedia

Problemi correlati