iOS4 и фон [UIImage setImage:] - PullRequest
8 голосов
/ 28 июня 2010

До 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.И если я сделаю [myImageView performSelectorOnMainThread:@selector(setImage:) withObject:newImage waitUntilDone:YES] вместо [myImageView setImage:newImage], изображения появятся немедленно, но, похоже, будут заново декодированы на лету (игнорируя предыдущий [UIImage imageNamed:], который должен был уже декодировать данные изображения), вызывая паузув моем главном потоке ... Даже если в документации написано Базовый кеш изображений используется всеми потоками. .

Есть мысли?

Ответы [ 4 ]

4 голосов
/ 28 июня 2010

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

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

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

3 голосов
/ 28 июня 2010

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

1 голос
/ 28 июня 2010

Давайте процитируем:

@property(nonatomic, readonly) 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 голос
/ 28 июня 2010

Если вы используете 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];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...