iOS4 и фон [UIImage setImage:]

До iOS 3.2 я использовал этот вид кода для загрузки UIImageView изображение в фоне, и это хорошо работало...

Код:

- (void)decodeImageName:(NSString *)name
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    UIImage *newImage = [UIImage imageNamed:name];
    [myImageView setImage:newImage];
    [pool release];
}
...
[self performSelectorInBackground:@selector(decodeImageName:) withObject:@"ID"]

... даже если [UIImageView setImage:] не было ориентировано на многопотоковое исполнение!

Но начиная с iOS 4, это больше не работает... Изображения появляются на экране спустя две секунды после этого setImage звонить. И если я делаю a [myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:YES] вместо [myImageView setImage:newImage], изображения сразу появляются, но, кажется, повторно декодируются снова на лету (игнорирующий предыдущее [UIImage imageNamed:] который должен был уже декодировать данные изображения), вызывая паузу на моем основном потоке... Даже если в документации говорится, что кэш основного изображения общий для все потоки..

Какая-либо мысль?

8
задан Damien Debin 5 November 2015 в 15:26
поделиться

4 ответа

Не делайте этого в фоновом режиме! Это не потокобезопасный. Поскольку UIImageView также является NSObject , я думаю, что использование - [performSelectorOnMainThread: withObject: waitUntilDone:] может сработать, например:

[myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:NO];

И это UIImage , который недавно стал потокобезопасным. UIImageView по-прежнему не является потокобезопасным.

4
ответ дан 5 December 2019 в 18:56
поделиться

performSelectorInBackground: запускает селектор в фоновом потоке.Но setImage: - это функция пользовательского интерфейса. Функции пользовательского интерфейса должны выполняться только в основном потоке. У меня нет понимания конкретной проблемы, но это первое впечатление об этом коде, и возможно, что iOS4 каким-то образом по-другому обрабатывает (не поддерживаемый) механизм запуска функций пользовательского интерфейса в фоновых потоках.

3
ответ дан 5 December 2019 в 18:56
поделиться

Если вы используете iOS 4.0, вам следует действительно рассмотреть возможность чтения блоков и GCD. Используя эти технологии, вы можете просто заменить свой метод на:

- (void)decodeImageName:(NSString *)name
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    UIImage *newImage = [UIImage imageNamed:name];

    dispatch_async(dispatch_get_main_queue(), ^{
        [myImageView setImage:newImage];
    }

    [pool release];
}
1
ответ дан 5 December 2019 в 18:56
поделиться

Процитируем:

@property (неатомарно, только для чтения) CGImageRef CGImage

Обсуждение

Если данные изображения были очищены из-за ограничений памяти, вызов этого метода заставляет эти данные для загрузки обратно в память. Повторная загрузка данных изображения может привести к снижению производительности.

Так что вы могли бы просто вызвать image.CGImage . Не думаю, что CGImages ленивы.

Если это не сработает, вы можете принудительно выполнить рендеринг с помощью чего-то вроде

// Possibly only safe in the main thread...
UIGraphicsBeginImageContext((CGSize){1,1});
[image drawInRect:(CGRect){1,1}];
UIGraphicsEndImageContext();

Некоторые люди предупреждают о потокобезопасности. В документации говорится, что UIGraphics {Push, Pop, GetCurrent} Context () работает только с основным потоком, но ничего не упоминается о UIGraphicsBeginImageContext () . Если вы беспокоитесь, используйте CGBitmapContextCreate и CGContextDrawImage .

1
ответ дан 5 December 2019 в 18:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: