2010-06-28 7 views
8

Hasta IOS 3.2, que utiliza este tipo de código para cargar la imagen UIImageView en el fondo, y funcionó bien ...iOS4 y de fondo [UIImage setImage:]

Código:

- (void)decodeImageName:(NSString *)name 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    UIImage *newImage = [UIImage imageNamed:name]; 
    [myImageView setImage:newImage]; 
    [pool release]; 
} 
... 
[self performSelectorInBackground:@selector(decodeImageName:) withObject:@"ID"] 

. .. incluso si [UIImageView setImage:] no era seguro para subprocesos!

Pero desde iOS 4, ya no funciona ... Las imágenes aparecen en la pantalla dos segundos después de la llamada setImage. Y si hago un [myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:YES] en lugar de [myImageView setImage:newImage], las imágenes aparecen inmediatamente pero parecen ser redecodificadas de nuevo sobre la marcha (ignorando el anterior [UIImage imageNamed:] que ya debería haber decodificado los datos de imagen), causando una pausa en mi hilo principal ... . Incluso si la documentación dice La memoria caché de imágenes subyacente se comparte entre todos los hilos..

¿Alguna idea?

+0

Hola, gracias por hacer esta pregunta.Me preguntaba por qué no funciona ahora con mi aplicación. – GeneCode

Respuesta

3

performSelectorInBackground: ejecuta un selector en una cadena de fondo. Sin embargo, setImage: es una función de interfaz de usuario. Las funciones de interfaz de usuario solo deben ejecutarse en el hilo principal. No tengo una idea del problema en particular, pero esta es la primera impresión sobre este código, y es posible que iOS4 maneje el mecanismo (no compatible) de ejecutar funciones de IU en hilos de fondo de alguna manera diferente.

4

¡No lo haga de fondo! No es seguro para subprocesos Desde un UIImageView es también un NSObject, creo que el uso de -[performSelectorOnMainThread:withObject:waitUntilDone:] en que podría funcionar, como:

[myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:NO]; 

Y es UIImage que está recién hecha flujos seguros. UIImageView aún no es seguro para subprocesos.

+1

Hola Evadne, ¿dónde has leído que UIImage es seguro para subprocesos? No puedo encontrar eso en ningún lado. – jasongregori

1

Si está utilizando iOS 4.0, debería realmente considerar leer en bloques y GCD. El uso de estas tecnologías, puede simplemente reemplazar su método con: cita

- (void)decodeImageName:(NSString *)name 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    UIImage *newImage = [UIImage imageNamed:name]; 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     [myImageView setImage:newImage]; 
    } 

    [pool release]; 
} 
+0

No ayuda mucho. El dispatch_async todavía pausa el hilo principal más tiempo de lo que debería ser como si el uiimage fuera recodificado. ¿Cómo puedo estar seguro de que el UIImage se decodifica después de [UIImage imageNamed: name]? –

+0

Recomendaría soportar OS 3.1.3 durante al menos varios meses, y 3.2 hasta unos meses después de que se lanzara 4.0+ para iPad. –

1

Repasemos:

@property(nonatomic, readonly) CGImageRef CGImage

Discusión

Si los datos de imagen se ha purgado a causa de la memoria restricciones, invocar este método obliga a que los datos se carguen de nuevo en la memoria. Recargar los datos de imagen puede incurrir en una penalización de rendimiento.

Así que es posible que solo pueda llamar al image.CGImage. No creo que CGImages sean flojos.

Si eso no funciona, puede forzar un render con algo como

// Possibly only safe in the main thread... 
UIGraphicsBeginImageContext((CGSize){1,1}); 
[image drawInRect:(CGRect){1,1}]; 
UIGraphicsEndImageContext(); 

Algunas personas advierten sobre hilos de seguridad. Los documentos dicen que UIGraphics{Push,Pop,GetCurrent}Context() son solo de subproceso principal, pero no mencionan nada sobre UIGraphicsBeginImageContext(). Si está preocupado, use CGBitmapContextCreate y CGContextDrawImage.

Cuestiones relacionadas