2012-05-28 15 views
20

Yaşadığım sorunu ve nasıl çözmeye çalıştığımı anlatayım. Alt görünümleri soldan sağa kaydırılmış olarak yükleyen bir UIScrollView var. Her alt görüntünün her biri 400x200 civarında 10-20 görüntüye sahiptir. Görünümden görünümüne kaydırdığımda, biraz gecikme yaşadım. İncelemeden sonra, tüm görüşleri boşalttıktan ve tekrar denedikten sonra gecikmenin ortadan kalktığını keşfettim. Görüntülerin senkronize önbelleğinin gecikmenin sebebi olduğunu düşündüm. Bu yüzden, görüntüleri eşzamansız olarak yükleyen bir UIImageView alt sınıfı oluşturdum. Yükleme kodu aşağıdaki gibi görünür (self.dispatchQueue bir seri gönderme sırasını döndürür).UIImageView görüntüsünün ayarlanması büyük gecikme neden olur

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

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

Ancak bu alt sınıfa benim UIImageViews tüm değiştirdikten sonra, hala (yüzlekleşmesi veya olmasaydı emin değilim) lag yaşadı. Sorunun nedenini self.image = image;'a kadar kaynattım. Bu neden bu kadar fazla gecikmeye neden oluyor (ancak sadece ilk yükte)?

Lütfen bana yardım edin. = (

cevap

51

sdk 4.2 ios5 iphone EDIT 2 test:.. İşte Swift versiyonu olduğunu Birkaç iyileştirme içerir. (Test edilmemiş.) https://gist.github.com/fumoboy007/d869e66ad0466a9c246d


DÜZENLEME: Aslında, gerekli olan her şeyin aşağıdaki olduğuna inanıyorum. (Test edilmemiş.)

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

ORİJİNAL CEVAP: O self.image = image; doğrudan değildi çıkıyor. UIImage görüntü yükleme yöntemleri, görüntü verilerini hemen sıkıştırmaz ve işlemez; Görünüm ekranını yenilediğinde yaparlar. Böylece çözüm Core Graphics'e daha düşük bir seviyeye gitmek ve görüntü verilerinin kendiliğinden açılması ve işlenmesiydi. Yeni kod aşağıdaki gibi görünüyor.

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

Oops… Bu küçük böcek için üzgünüm. – fumoboy007

+0

Bu çok yardımcı oldu. UIView'den UIImage yapması gereken bu soruya gelen insanlar için birçok çözümden sonra bu çözümü buldum: 'UIGraphicsBeginImageContext (processing.bounds.size); 'CGContextRef ctx = UIGraphicsGetCurrentContext(); '[processing.layer renderInContext: ctx]; 'UIImage * finalImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); ' –

+0

Teşekkür ederiz! .... –

1

Sanırım, bu problem Görüntülerin kendileri olabilir.Örneğin - Projelerimden birinde 10 adet 640x600 alfa saydamlık ile katmanlandım.Görüntüleyiciyi bu viewcontroller'dan itmeye veya göstermeye çalıştığımda .. bir sürü kalıyor

oldukça küçük resimler sadece birkaç fotoğraf bırakın veya kullandığınızda - hayır gecikme

PS 4.

+1

Ancak benimki sadece ilk yükte kalıyor! – fumoboy007