2012-05-28 8 views
20

Déjame que te cuente sobre el problema que tengo y cómo traté de resolverlo. Tengo un UIScrollView que carga las subvistas a medida que se desplaza de izquierda a derecha. Cada subvista tiene 10-20 imágenes alrededor de 400x200 cada una. Cuando me desplazo de la vista a la vista, experimento bastante retraso.Establecer la propiedad de la imagen de UIImageView causa un retraso mayor

Después de investigar, descubrí que después de descargar todas las vistas e intentarlo de nuevo, el retraso se había ido. Pensé que el almacenamiento síncrono de las imágenes fue la causa del retraso. Así que creé una subclase de UIImageView que cargó las imágenes de forma asíncrona. El código de carga es similar al siguiente (self.dispatchQueue devuelve una cola de despacho en serie).

- (void)loadImageNamed:(NSString *)name { 
    dispatch_async(self.dispatchQueue, ^{ 
     UIImage *image = [UIImage imageNamed:name]; 

     dispatch_sync(dispatch_get_main_queue(), ^{ 
      self.image = image; 
     }); 
    }); 
} 

Sin embargo, después de cambiar todos mis UIImageViews a esta subclase, todavía experimenta lag (no estoy seguro si fue disminuida o no). Reduje la causa del problema a self.image = image;. ¿Por qué esto causa tanta demora (pero solo en la primera carga)?

Por favor, ayúdame. = (

Respuesta

51

EDIT 2:.. he aquí una versión que Swift contiene algunas mejoras. (No comprobado.) https://gist.github.com/fumoboy007/d869e66ad0466a9c246d


EDITAR: En realidad, creo que todo lo que es necesario es lo siguiente. (No probado.)

- (void)loadImageNamed:(NSString *)name { 
    dispatch_async(self.dispatchQueue, ^{ 
     // Determine path to image depending on scale of device's screen, 
     // fallback to 1x if 2x is not available 
     NSString *pathTo1xImage = [[NSBundle mainBundle] pathForResource:name ofType:@"png"]; 
     NSString *pathTo2xImage = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"png"]; 

     NSString *pathToImage = ([UIScreen mainScreen].scale == 1 || !pathTo2xImage) ? pathTo1xImage : pathTo2xImage; 


     UIImage *image = [[UIImage alloc] initWithContentsOfFile:pathToImage]; 

     // Decompress image 
     if (image) { 
      UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale); 

      [image drawAtPoint:CGPointZero]; 

      image = UIGraphicsGetImageFromCurrentImageContext(); 

      UIGraphicsEndImageContext(); 
     } 


     // Configure the UI with pre-decompressed UIImage 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      self.image = image; 
     }); 
    }); 
} 

respuesta original: Resulta que no era self.image = image; directamente. Los métodos de carga de imágenes UIImage no descomprimen y procesan los datos de imagen de inmediato; lo hacen cuando la vista actualiza su visualización. Así que la solución fue bajar un nivel a Core Graphics y descomprimir y procesar los datos de imagen yo mismo. El nuevo código se parece a lo siguiente.

- (void)loadImageNamed:(NSString *)name { 
    dispatch_async(self.dispatchQueue, ^{ 
     // Determine path to image depending on scale of device's screen, 
     // fallback to 1x if 2x is not available 
     NSString *pathTo1xImage = [[NSBundle mainBundle] pathForResource:name ofType:@"png"]; 
     NSString *pathTo2xImage = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"png"]; 

     NSString *pathToImage = ([UIScreen mainScreen].scale == 1 || !pathTo2xImage) ? pathTo1xImage : pathTo2xImage; 


     UIImage *uiImage = nil; 

     if (pathToImage) { 
      // Load the image 
      CGDataProviderRef imageDataProvider = CGDataProviderCreateWithFilename([pathToImage fileSystemRepresentation]); 
      CGImageRef image = CGImageCreateWithPNGDataProvider(imageDataProvider, NULL, NO, kCGRenderingIntentDefault); 


      // Create a bitmap context from the image's specifications 
      // (Note: We need to specify kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little 
      // because PNGs are optimized by Xcode this way.) 
      CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
      CGContextRef bitmapContext = CGBitmapContextCreate(NULL, CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerComponent(image), CGImageGetWidth(image) * 4, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little); 


      // Draw the image into the bitmap context 
      CGContextDrawImage(bitmapContext, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); 

      // Extract the decompressed image 
      CGImageRef decompressedImage = CGBitmapContextCreateImage(bitmapContext); 


      // Create a UIImage 
      uiImage = [[UIImage alloc] initWithCGImage:decompressedImage]; 


      // Release everything 
      CGImageRelease(decompressedImage); 
      CGContextRelease(bitmapContext); 
      CGColorSpaceRelease(colorSpace); 
      CGImageRelease(image); 
      CGDataProviderRelease(imageDataProvider); 
     } 


     // Configure the UI with pre-decompressed UIImage 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      self.image = uiImage; 
     }); 
    }); 
} 
+0

Vaya ... disculpa por ese pequeño error. – fumoboy007

+0

Esto fue muy útil. Para las personas que llegan a esta pregunta y solo necesitan realizar un UIImage desde una UIView, encontré esta solución después de completar muchas respuestas: 'UIGraphicsBeginImageContext (processing.bounds.size); 'CGContextRef ctx = UIGraphicsGetCurrentContext(); '[processing.layer renderInContext: ctx]; 'UIImage * finalImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); ' –

+0

¡Gracias! ... –

1

Creo que el problema podrían ser las imágenes mismas. Por ejemplo, obtuve en uno de mis proyectos 10 imágenes de 640x600 capas con transparencia alfa entre sí. Cuando intento presionar o abrir el controlador de vista desde este controlador de vista ... que queda mucho

cuando deje sólo pocas imágenes o utilizar imágenes bastante más pequeños - sin retraso

PS probado en SDK 4.2 iOS5 iPhone 4.

+1

¡Pero la mía solo se demora en la primera carga! – fumoboy007

Cuestiones relacionadas