Я прочитал много UIScrollView с потоками UIImageView здесь или других гугл-страниц. Но я все еще не могу понять проблему, с которой сталкиваюсь. У меня сейчас простуда. Надеюсь, я все еще могу это прояснить, смеется. Вот проблема:
Я создаю одно приложение, которое в основном использует UIScrollView для отображения нескольких изображений. Здесь учитывается количество, а не размер, который в среднем составляет 100 КБ (я даже конвертировал PNG в JPG, не уверен, помогает это или нет). При наличии не более 10 изображений мое приложение падает с предупреждением памяти. Это первый раз, когда я сталкиваюсь с проблемой памяти, которая удивила меня, поскольку размер скомпилированного приложения составляет менее 10 МБ.
В самом начале я загружаю все изображения при запуске, зацикливаю все имена файлов изображений и делаю
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imgName]];
[scrollview addSubview:imageView];
[imageView release];
Если я прав, думаю после запуска все образы в памяти, верно? Но самое забавное здесь то, что приложение может запускаться без каких-либо проблем (самое большее предупреждение о уровне памяти 1). После того, как я прокрутил несколько изображений, он упал. Я проверял утечки наверняка, а также распределение. Отсутствие утечек и выделения практически не изменилось во время прокрутки.
Итак, есть ли что-то особенное, сделанное imageNamed, а не кешем?
А потом, да, я повернулся к ленивой нагрузке.
Поскольку страх проверки страницы и загрузки изображений по требованию может привести к рывкам при прокрутке (что подтвердилось), я использовал поток, который запускает цикл для проверки смещения вида прокрутки и загрузки / выгрузки изображений.
Я создал подкласс UIImageView, запомнив имя изображения. Он также содержит loadImage и unloadImage, которые будут выполняться в этом потоке.
- (void)loadImage {
/<em>if ([self.subviews count] == 0) {
UIImageView</em> iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:self.imageName]];
[self performSelectorOnMainThread:@selector(renderImage:) withObject:iv waitUntilDone:NO];
//[self addSubview:iv];
[iv release];
}*/</p>
<pre><code>if (self.image == nil) {
//UIImage *img = [UIImage imageNamed:self.imageName];
UIImage *img = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[self.imageName stringByDeletingPathExtension] ofType:[self.imageName pathExtension]]];
// image must be set on main thread as UI rendering is main thread's responsibility
[self performSelectorOnMainThread:@selector(renderImage:) withObject:img waitUntilDone:NO];
[img release];
}
* *} Тысяча двадцать-один
// отображаем изображение в главном потоке
- (void) renderImage: (UIImage *) iv {
// [self addSubview: iv];
self.image = iv;
}
- (void) unloadImage {
self.image = ноль;
//[(UIView*)[self.subviews lastObject] removeFromSuperview];
}
Вы можете увидеть закомментированный код, с которым я играл.
В unloadImage, если я напишу [self.image release]
, я получу EXC_BAD_ACCESS, что неожиданно, так как я думаю, что alloc и release совпадают.
Приложение по-прежнему падает без утечки. Версия initWithContentsOfFile
даже вылетала раньше, чем версия imageNamed, и прокрутка была не такой плавной.
Я запускаю приложение на устройстве. Проверив распределение, я обнаружил, что imageNamed
версия использовала намного меньше памяти, чем initWithContentsOfFile
версия, хотя они оба вылетали. Инструменты также показали, что выделенные изображения были 2,3 или 4, что указывало на то, что ленивая нагрузка справилась со своей задачей.
Я проверил PhotoScroller WWDC2010, но я не думаю, что это решает мою проблему. Нет масштабирования или огромного изображения.
Кто-нибудь помогает! Заранее спасибо.