2012-05-28 95 views
20

让我告诉你我遇到的问题以及我如何解决它。我有一个UIScrollView作为一个滚动从左到右加载子视图。每个子视图都有大约400x200的10-20幅图像。当我从视图滚动到视图时,我经历了相当多的滞后。设置UIImageView的图像属性导致严重滞后

经过调查,我发现在卸下所有视图并再次尝试之后,延迟消失了。我认为图像的同步缓存是滞后的原因。所以我创建了一个UIImageView的子类,它异步加载图像。加载代码如下所示(self.dispatchQueue返回一个串行调度队列)。

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

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

然而,我的所有的UIImageViews的更改为此子后,我还是经历了滞后(我不知道这是否是减少或没有)。我把问题的原因归结为self.image = image;。为什么这会造成很大的滞后(但只在第一次加载时)?

请帮帮我。 =(

回答

51

编辑2:这里是一个斯威夫特版本包含一些改进(未测试) https://gist.github.com/fumoboy007/d869e66ad0466a9c246d


编辑:其实,我相信所有必要的是以下内容。 (未经测试)

- (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; 
     }); 
    }); 
} 

原来的答案:事实证明,这不是self.image = image;直接。 UIImage图像加载方法不会立即解压缩和处理图像数据;他们在视图刷新显示时执行此操作。所以解决方案是降低到Core Graphics的水平,并自己解压缩和处理图像数据。新代码如下所示。

- (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

糟糕...对那个小错误感到抱歉。 – fumoboy007

+0

这非常有帮助。对于这个问题的人只是需要从UIView中创建一个UIImage,我在通过很多答案进行拼接后发现了这个解决方案: 'UIGraphicsBeginImageContext(processing.bounds.size); 'CGContextRef ctx = UIGraphicsGetCurrentContext(); '[processing.layer renderInContext:ctx]; 'UIImage * finalImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();' –

+0

Thank you!.... –

1

我认为,问题可能是图片本身。例如 - 我在我的项目之一中获得了10张图片640x600,其中每张图片上都带有alpha透明度,当我尝试从该viewcontroller推送或弹出viewcontroller ..它落后了很多

,当我离开只有少数图像或使用非常小的图像 - 没有滞后

PS的SDK 4.2 iOS5的iPhone 4测试

+1

但是,我只在第一个负载上滞后! – fumoboy007

相关问题