L’impostazione della proprietà dell’immagine di UIImageView causa un lag maggiore

Lascia che ti parli del problema che sto avendo e di come ho cercato di risolverlo. Ho un UIScrollView che carica le sottoview come si scorre da sinistra a destra. Ogni sottoview contiene 10-20 immagini di circa 400×200 ciascuna. Quando scorro dalla vista alla vista, provo un bel po ‘di ritardo.

Dopo aver indagato, ho scoperto che dopo aver scaricato tutte le viste e provato di nuovo, il ritardo era scomparso. Ho capito che la cache sincrona delle immagini era la causa del ritardo. Così ho creato una sottoclass di UIImageView che caricava le immagini in modo asincrono. Il codice di caricamento è simile al seguente ( self.dispatchQueue restituisce una coda di invio seriale).

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

Tuttavia, dopo aver modificato tutte le mie UIImageViews in questa sottoclass, ho comunque riscontrato un ritardo (non sono sicuro che fosse diminuito o meno). Ho ridotto la causa del problema a self.image = image; . Perché questo provoca così tanto ritardo (ma solo sul primo carico)?

Mi aiuti per favore. = (

EDIT 2: Ecco una versione di Swift che contiene alcuni miglioramenti. (Non verificato.) https://gist.github.com/fumoboy007/d869e66ad0466a9c246d


EDIT: In realtà, credo che tutto ciò che è necessario è il seguente. (Non testato.)

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

RISPOSTA ORIGINALE: Si scopre che non era self.image = image; direttamente. I metodi di caricamento dell’immagine UIImage non decomprimono e elaborano i dati dell’immagine immediatamente; lo fanno quando la vista aggiorna la visualizzazione. Quindi la soluzione era di scendere di livello in Core Graphics e decomprimere ed elaborare i dati dell’immagine da solo. Il nuovo codice ha il seguente aspetto.

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

Penso che il problema potrebbe essere le immagini stesse. Ad esempio, ho ottenuto in uno dei miei progetti 10 immagini 640×600 sovrapposte con trasparenza alfa l’una sull’altra. Quando provo a spingere o far apparire viewcontroller da questo viewcontroller .. è molto lento.

quando lascio solo poche immagini o uso immagini più piccole – nessun ritardo.

PS testato su sdk 4.2 ios5 iphone 4.