2012-05-28 3 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

SDK 4.2 iOS5를 아이폰에 편집 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; 
     }); 
    }); 
} 

ORIGINAL 답변 : 그것은 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

감사합니다 .... .... –

1

내가 생각하기에 문제는 이미지 자체 일 수 있습니다. 예를 들어 - 내 프로젝트 10 이미지 640x600 서로 알파 투명도로 계층화 된 있어요. 내가 pushcontrol 또는 viewcontroller이 viewcontroller 팝업 때. 그것은 많이 지연

나는 아주 작은 이미지 만 몇 이미지를 떠나거나 사용할 때 - 더 지연

PS 4.

+1

하지만 첫 번째로드에서만 지연됩니다. – fumoboy007

관련 문제