2012-10-06 12 views
5

Próbuję prosty test dla bardziej złożonego projektu, ale jestem zaskoczony, dlaczego poniższy kod ulega awarii i daje błąd EXC_BAD_ACCESS?UIImage z CGImageRef

To się nazywa z 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]; 
} 

Domyślam się, że CGImageRef nie jest zachowana, ale dodanie CGImageRetain (imageRef); nie robi różnicy.

Należy również zauważyć, że ten projekt ma włączoną funkcję ARC.

EDIT

zrobiłem trochę więcej badań i odkryli, że jest to bezpośrednio związane z ARC jak stworzyłem 2 podstawowych projektów w tym jedynym powyższym kodzie. Pierwszy z ARC wyłączony i działał idealnie. Następna z włączonym ARC i awarią BAM z tym samym błędem. Interesujące jest to, że mam rzeczywisty błąd logowania TYLKO przy pierwszym uruchomieniu projektu przed awarią.

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

Odpowiedz

9

Linia ta jest problem:

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

Utworzona UIImage ukaże się natychmiast po tym pełnowymiarowych wyrażenie (np. po tej linii). Nawet próba dodania CGImageRetain() nie zadziała.

Podstawowym problemem jest CGImageRef wrócił z CGImage jest prawie na pewno Ivar z UIImage i zostanie wydana, gdy UIImage jest deallocted.

Ogólny sposób naprawy polega na wydłużeniu okresu eksploatacji modelu UIImage. Możesz to zrobić, umieszczając UIImage w zmiennej lokalnej i odwołując się do niej po ostatnim odwołaniu do CGImage (np. Z (void)uiimageVar). Alternatywnie, można zachować CGImageRef na tej samej linii, co w

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

Ale jeśli to zrobisz, nie zapomnij, aby zwolnić imageRef kiedy skończysz.

5

Napisałeś to:

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

Linia ta tworzy UIImage, dostaje swoją CGImage własność, a następnie zwalnia obiekt UIImage. Ponieważ nie przechowujesz w tej linii CGImage, jedynym właścicielem CGImage jest UIImage. Kiedy zwolni się UIImage i natychmiast zwróci się, zwalnia również CGImage.

Musisz zachować CGImage przed zwolnieniem UIImage. Spróbuj tego:

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

a potem na końcu funkcji:

CGImageRelease(imageRef); 
+0

Fantastycznie, teraz widzę dokładnie, co się dzieje. Przynajmniej byłem na dobrej drodze. Dzięki Rob. – EcksMedia