Подтвердить что ты не робот

Установка свойства изображения UIImageView вызывает серьезное отставание

Позвольте мне рассказать вам о проблеме, которую я испытываю, и о том, как я пытался ее решить. У меня есть UIScrollView, который загружает subviews как один прокручивается слева направо. Каждый subview имеет 10-20 изображений по 400x200 каждый. Когда я перехожу от просмотра к представлению, я испытываю довольно небольшое отставание.

После расследования я обнаружил, что после разгрузки всех взглядов и повторного пробуждения отставание исчезло. Я понял, что синхронное кэширование изображений стало причиной отставания. Поэтому я создал подкласс 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;. Почему это вызывает столько задержек (но только при первой загрузке)?

Пожалуйста, помогите мне. = (

4b9b3361

Ответ 1

EDIT 2: Вот версия Swift, которая содержит несколько улучшений. (Непроверенные). https://gist.github.com/fumoboy007/d869e66ad0466a9c246d


EDIT: На самом деле, я считаю, что все, что необходимо, следующее. (Тестировалась.)

- (void)loadImageNamed:(NSString *)name {
    dispatch_async(self.dispatchQueue, ^{
        // Determine path to image depending on scale of device 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 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 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;
        });
    });
}

Ответ 2

Думаю, проблема может быть в самих Картах. Например, я попал в один из моих проектов 10 изображений 640x600, слоистых с альфа-прозрачностью друг на друга. Когда я пытаюсь нажать или вызвать viewcontroller из этого диспетчера представлений, он значительно отстает.

когда я оставляю только несколько изображений или использую довольно маленькие изображения - без задержек.

P.S. протестировано на sdk 4.2 ios5 iphone 4.