Возможна оптимизация для выгрузки представлений + контроллеров, которые больше не видны в UIScrollView и PageControl - PullRequest
3 голосов
/ 28 марта 2011

У меня такой же код управления страницей, что и в примере с яблоком.Здесь у меня есть подпредставление (controller.view), которое содержит ImageView.Теперь проблема с управлением памятью.Все работает отлично.Но когда я прокручиваю 5-10 страниц.RAM заполняется.Я пытался освободить контроллер view +, но не нашел подходящего места / способа работы.Я хочу освободить представления, которые в настоящее время не видны.(кроме текущего, предыдущего и следующего просмотра)

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    NSMutableArray *controllers = [[NSMutableArray alloc] init];
    for (unsigned i = 0; i < kNumberOfPages; i++) {
        [controllers addObject:[NSNull null]];
    }
    self.viewControllers = controllers;
    [controllers release];

    scrollView.pagingEnabled = YES;
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.showsVerticalScrollIndicator = NO;
    scrollView.scrollsToTop = NO;
    scrollView.delegate = self;

    pageControl.numberOfPages = kNumberOfPages;
    pageControl.currentPage = 0;

    [self loadScrollViewWithPage:0];
    [self loadScrollViewWithPage:1];
}
- (void)loadScrollViewWithPage:(int)page {
    if (page < 0) return;
    if (page >= kNumberOfPages) return;

    PageControlExampleViewControl *controller = [viewControllers objectAtIndex:page];
    if ((NSNull *)controller == [NSNull null]) {
        controller = [[PageControlExampleViewControl alloc] initWithPageNumber:page];
        [viewControllers replaceObjectAtIndex:page withObject:controller];
        [controller release];
    }

    if (nil == controller.view.superview) {
        CGRect frame = scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
        controller.view.frame = frame;
        [scrollView addSubview:controller.view];
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)sender {
  if (pageControlUsed) {
        return;
    }
    CGFloat pageWidth = scrollView.frame.size.width;
    int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    pageControl.currentPage = page;

    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];

}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    pageControlUsed = NO;
}
- (IBAction)changePage:(id)sender {
    int page = pageControl.currentPage;
    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];
    CGRect frame = scrollView.frame;
    frame.origin.x = frame.size.width * page;
    frame.origin.y = 0;
    [scrollView scrollRectToVisible:frame animated:YES];
    pageControlUsed = YES;
}

Ответы [ 4 ]

4 голосов
/ 11 июня 2011

Я несколько часов пробовал код Deepmist. Он сделал свою работу, но я получил предупреждения памяти, и мое приложение падало каждые 25-30 прокручиваемых страниц (я использую большие изображения на страницах). В Инструментах я заметил очень большое использование памяти: даже если ненужные представления время от времени удалялись из суперпредставления, а относительные контроллеры представления заменялись NSNulls, Инструменты показали, что реальная память увеличивалась на каждом цикле прокрутки страниц на 4-5 МБ!

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

1) в каждом представлении обязательно используйте imageWithContentsOfFile вместо imageNamed. Как документировано изображение в кеше изображения и увеличение объема памяти.

2) в коде Deepmist, после:

[controller.view removeFromSuperview];

Вы также должны установить нулевое представление:

controller.view=nil;

Этот трюк решил проблему потребления памяти, которая теперь стабильна только для трех загруженных представлений (текущий, текущий-1 и текущий + 1, чтобы избежать мигания при прокрутке страниц).

Надеюсь, это поможет!

1 голос
/ 29 марта 2011

Я не проверял это, но я думаю, что вы могли бы написать метод, который противоположен загрузке, вот так:

- (void)unloadScrollViewWithPage:(int)page {
    if (page < 0) return;
    if (page >= kNumberOfPages) return;

    PageControlExampleViewControl *controller = [viewControllers objectAtIndex:page];

    if ((NSNull *)controller != [NSNull null]) {
        if (nil != controller.view.superview)
            [controller.view removeFromSuperview];

        [viewControllers replaceObjectAtIndex:page withObject:[NSNull null]];            
    }
}

Затем добавьте код в ваш метод didScroll следующим образом:

[self unloadScrollViewWithPage:page - 2];
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
[self unloadScrollViewWithPage:page + 2];
0 голосов
/ 24 июня 2013

try this VSScrollview, он использует свои представления так же, как UITableview использует свою ячейку.

0 голосов
/ 29 марта 2011

в методе loadScrollViewWithPage, непосредственно перед if (nil == controller.view.superview), циклически переберите все представления и удалите их все, кроме current -1, current и current + 1, но только если метод был вызван с текущим представлением индекса. Также не забудьте заменить эти контроллеры представления в массиве viewControllers на NSNulls.

...