Моя программа отображает горизонтальную прокручиваемую поверхность, облицованную UIImageViews слева направо. Код работает в потоке пользовательского интерфейса, чтобы убедиться, что вновь видимые UIImageViews имеют только что загруженный UIImage, назначенный им. Погрузка происходит в фоновом потоке.CGImage/UIImage lazily loading on UI thread заставляет заикаться
Все работает почти нормально, за исключением того, что заикается, когда каждое изображение становится видимым. Сначала я подумал, что мой фоновый работник блокировал что-то в потоке пользовательского интерфейса. Я потратил много времени на это, и в конце концов понял, что UIImage делает некоторую дополнительную ленивую обработку в потоке пользовательского интерфейса, когда она становится видимой. Это меня озадачивает, так как мой рабочий поток имеет явный код для распаковки данных JPEG.
Во всяком случае, на догадку я написал код для визуализации во временный графический контекст на фоне потока и - конечно же, заикание ушло. UIImage теперь предварительно загружается в рабочий поток. Все идет нормально.
Проблема в том, что мой новый метод «сила ленивой загрузки изображения» ненадежен. Это вызывает прерывистый EXC_BAD_ACCESS. Я не знаю, что делает UIImage за кадром. Возможно, это распаковка данных JPEG. Во всяком случае, этот метод:
+ (void)forceLazyLoadOfImage: (UIImage*)image
{
CGImageRef imgRef = image.CGImage;
CGFloat currentWidth = CGImageGetWidth(imgRef);
CGFloat currentHeight = CGImageGetHeight(imgRef);
CGRect bounds = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
CGAffineTransform transform = CGAffineTransformIdentity;
CGFloat scaleRatioX = bounds.size.width/currentWidth;
CGFloat scaleRatioY = bounds.size.height/currentHeight;
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, scaleRatioX, -scaleRatioY);
CGContextTranslateCTM(context, 0, -currentHeight);
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, CGRectMake(0, 0, currentWidth, currentHeight), imgRef);
UIGraphicsEndImageContext();
}
И EXC_BAD_ACCESS происходит на линии CGContextDrawImage. ВОПРОС 1: Могу ли я сделать это в потоке, отличном от потока пользовательского интерфейса? ВОПРОС 2: Что такое UIImage на самом деле «до загрузки»? ВОПРОС 3: Каков официальный способ решения этой проблемы?
Спасибо, что прочитали все это, любые советы были бы очень признательны!
привет, спасибо, что нашли время, чтобы помочь с этим. В конце концов я пришел к такому осознанию. Я могу только представить, какое злое небезопасное кэширование происходит внутри этих методов UI *. Мой интерфейс теперь заикается бесплатно ..... – JBx
Я в замешательстве ... вы говорите imageNamed: вызывает ленивый файл IO, но .. создание объекта данных не будет? Или вы говорите, что у вас должны собираться объекты данных, где-то, чтобы они были извлечены, когда это необходимо? –
Jasconius: Если вы создаете объект UIImage и передаете ему путь к файлу, он может не загружать все изображение в память, пока вы его не нарисуете. Если вы загружаете файл в память с помощью объекта NSData, передайте его в UIImage, у него нет выбора, кроме как сохранить его в памяти. Что лучше всего зависит от конкретной ситуации. – benzado