UIScrollView с UIImageView, UIImage - PullRequest
       5

UIScrollView с UIImageView, UIImage

0 голосов
/ 31 января 2011

Я прочитал много 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, но я не думаю, что это решает мою проблему. Нет масштабирования или огромного изображения.

Кто-нибудь помогает! Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 12 января 2012

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

имя массива: examplearray и имя представления: exampleview

-(void)updateImagesInScrollView
{



    int cnt = [examplearray count];

    for(int j=0; j< cnt; ++j)
    {
        NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:@"exampleview" 
                                                             owner:self 
                                                           options:nil];

        UIView *myView = [nibContents objectAtIndex:0];
        exampleview * rview= (exampleview *)myView;
        /* you can get your iamge from the array and set the image*/ 
        rview.imageview.image = yourimage;
        /*adding the view to your scrollview*/
        [self.ScrollView addSubview:rview];
    }
    /* you need to set  the content size of the scroll view */
    self.ScrollView.contentSize = CGSizeMake(X, self.mHorizontalScrollView.contentSize.height);
}
0 голосов
/ 12 января 2012

Неважно, какой формат вы используете для своих изображений. Когда вы отображаете их, они преобразуются в растровые изображения.

Я бы предложил использовать технику, аналогичную той, которая используется в UITableView (скрыть изображение и освободить используемую память, когда оно исчезает с экрана, и создавать экземпляр изображения только тогда, когда вам нужно его показать). 1003 *

В качестве альтернативы - если вам нужно показать эти изображения в виде сетки - вы можете взглянуть на CATiledLayer.

Во всяком случае, загрузка всех изображений в память - не лучшая идея:)

0 голосов
/ 31 января 2011

В журнале аварий ничего не сказано.Приложение аварийно завершает работу после того, как уровень предупреждения о памяти = 2. И если запустить на симуляторе, проблем не будет.

...