2012-05-28 39 views
20

Hãy để tôi cho bạn biết về vấn đề tôi đang gặp phải và cách tôi cố giải quyết nó. Tôi có một UIScrollView tải subviews như một cuộn từ trái sang phải. Mỗi subview có 10-20 hình ảnh khoảng 400x200 mỗi. Khi tôi cuộn từ chế độ xem sang chế độ xem, tôi gặp phải một chút chậm trễ.Đặt thuộc tính hình ảnh của UIImageView gây lag lớn

Sau khi điều tra, tôi phát hiện ra rằng sau khi dỡ tất cả các khung nhìn và thử lại lần nữa, độ trễ đã biến mất. Tôi thấy rằng bộ nhớ đệm đồng bộ của hình ảnh là nguyên nhân của độ trễ. Vì vậy, tôi đã tạo một lớp con của UIImageView đã tải hình ảnh một cách không đồng bộ. Mã tải trông giống như sau (self.dispatchQueue trả về hàng đợi công văn nối tiếp).

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

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

Tuy nhiên, sau khi thay đổi tất cả các UIImageView thành lớp con này, tôi vẫn gặp sự cố (tôi không chắc liệu nó có bị giảm hay không). Tôi đã đun sôi nguyên nhân của sự cố xuống self.image = image;. Tại sao điều này gây ra quá nhiều lag (nhưng chỉ trên tải đầu tiên)?

Hãy giúp tôi. = (

Trả lời

51

EDIT 2:.. đây là một phiên bản Swift rằng có một số cải tiến. (Chưa được kiểm tra.) https://gist.github.com/fumoboy007/d869e66ad0466a9c246d


EDIT: Trên thực tế, tôi tin rằng tất cả những gì cần thiết là như sau. (Chưa được kiểm tra.)

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

ĐÁP ORIGINAL: Nó chỉ ra rằng đó không phải là self.image = image; trực tiếp. Phương thức tải hình ảnh UIImage không giải nén và xử lý dữ liệu hình ảnh ngay lập tức; họ làm điều đó khi chế độ xem làm mới màn hình của nó. Vì vậy, giải pháp là để đi một mức độ thấp hơn để đồ họa cốt lõi và giải nén và xử lý dữ liệu hình ảnh bản thân mình. Mã mới trông giống như sau.

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

Rất tiếc ... xin lỗi về lỗi nhỏ đó. – fumoboy007

+0

Điều này rất hữu ích. Đối với những người đến câu hỏi này chỉ cần thực hiện một UIImage từ một UIView, tôi tìm thấy giải pháp này sau khi ghép qua nhiều câu trả lời: 'UIGraphicsBeginImageContext (processing.bounds.size); 'CGContextRef ctx = UIGraphicsGetCurrentContext(); '[processing.layer renderInContext: ctx]; 'UIImage * finalImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); ' –

+0

Cảm ơn bạn! .... –

1

Tôi nghĩ rằng, vấn đề có thể là hình ảnh của mình. Ví dụ - tôi nhận được một trong các dự án của tôi 10 hình ảnh 640x600 lớp với độ trong suốt alpha trên mỗi khác .. Khi tôi cố gắng để đẩy hoặc pop viewcontroller từ viewcontroller này .. nó thua rất nhiều

khi tôi rời khỏi chỉ vài hình ảnh hoặc sử dụng hình ảnh khá nhỏ - không lag

PS thử nghiệm trên sdk 4.2 ios5 iphone 4.

+1

Nhưng tôi chỉ bị trễ khi tải đầu tiên! – fumoboy007

Các vấn đề liên quan