UIScrollView和真实内存

时间:2012-01-31 09:45:17

标签: iphone ios ipad uiscrollview uiimageview

我观看了WWDC 2010 104关于在UIScrollView上实现平铺的会话,我试图通过一些更改来实现它,但我有实内存的问题 - 我将UIImageView作为子视图添加到UIScrollView,我甚至尝试在添加后立即删除超级视图 - 而且我没有清理真正的记忆。总而言之。 可能是自动释放有问题吗?

- (void)tilePages 
{
    [scrollView setContentSize:CGSizeMake(scrollView.bounds.size.width * [images count], scrollView.bounds.size.height)]; 

    CGRect visibleBounds = scrollView.bounds;
    int firstNeededPageIndex = floorf(CGRectGetMinX(visibleBounds) / CGRectGetWidth(visibleBounds));
    int lastNeededPageIndex  = floorf((CGRectGetMaxX(visibleBounds)-1) / CGRectGetWidth(visibleBounds));
    firstNeededPageIndex = MAX(firstNeededPageIndex, 0);
    lastNeededPageIndex  = MIN(lastNeededPageIndex, ([images count] - 1));

    for (ImageScrollView *page in visiblePages) {
        if (page.index < firstNeededPageIndex || page.index > lastNeededPageIndex) {
            [recycledPages addObject:page];
            [page removeFromSuperview];
        }
    }

    [visiblePages minusSet:recycledPages];

    for (int index = firstNeededPageIndex; index <= lastNeededPageIndex; index++) {
        if (![self isDisplayingPageForIndex:index]) {
            ImageScrollView *page = [self dequeueRecycledPage];
            if (page == nil) {
                page = [[[ImageScrollView alloc] init] autorelease];

                [page setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];

                if (self.interfaceOrientation == UIInterfaceOrientationPortrait || self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
                    [page setContentMode:UIViewContentModeScaleAspectFill];
                } 
                else {
                    [page setContentMode:UIViewContentModeScaleAspectFit];
                }
            }
            [self configurePage:page forIndex:index];

            [scrollView addSubview:page];

            [visiblePages addObject:page];
        }
    }    
}

- (ImageScrollView *)dequeueRecycledPage
{
    ImageScrollView *page = [recycledPages anyObject];
    if (page) {
        [[page retain] autorelease];
        [recycledPages removeObject:page];
    }
    return page;
}

- (BOOL)isDisplayingPageForIndex:(NSUInteger)index
{
    BOOL foundPage = NO;
    for (ImageScrollView *page in visiblePages) {
        if (page.index == index) {
            foundPage = YES;
            break;
        }
    }
    return foundPage;
}

- (void)configurePage:(ImageScrollView *)page forIndex:(NSUInteger)index
{
    page.index = index;
    page.frame = [self frameForPageAtIndex:index];
    [page displayImage:[self imageAtIndex:index]];
}

- (CGRect)frameForPagingScrollView 
{
    CGRect frame = scrollView.bounds;
    return frame;
}

- (CGRect)frameForPageAtIndex:(NSUInteger)index {
    CGRect pagingScrollViewFrame = [self frameForPagingScrollView];

    CGRect pageFrame = pagingScrollViewFrame;
    pageFrame.origin.x = (pagingScrollViewFrame.size.width * index);
    return pageFrame;
}

- (UIImage *)imageAtIndex:(NSUInteger)index {
    return [images objectAtIndex:index];   
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.scrollView = nil;
    self.textView = nil;
}

- (void)dealloc
{
     [super dealloc];
     [scrollView release];
     [images release];
     [recycledPages release];
     [visiblePages release];
}

1 个答案:

答案 0 :(得分:0)

除了一个部分之外,您已正确实现了演示。内存应该在

行发布
[visiblePages minusSet:recycledPages];

但是我可以看到你将图像存储在一个数组中。您的图像被该阵列保留,并且没有被释放,因此占用了内存。

此代码的目标是在需要时懒洋洋地加载图像。您不会发布初始化图像阵列的位置,但是从您拥有的图像阵列预先填充图像。

相反,你应该将图像路径存储在数组中(到目前为止你用它做的所有事情仍然可以工作),然后改变以下方法:

- (UIImage *)imageAtIndex:(NSUInteger)index {
    NSSting * imagePath = [images objectAtIndex:index];
    UIImage * image = [UIImage imageWithContentsOfFile:imagePath];
    return image;   
}

或者那种效果。根据图像的来源,可能有更有效的加载图像的方法,但上面应该可以停止崩溃。

如果您的图片需要很长时间才能加载并阻止您的界面,您可以执行以下操作。您可以使用GCD将图像加载卸载到后台线程,或者您可以继续观看该WWDC视频并为高分辨率图像实现CATiledLayer并将其放置在低分辨率图像上。图像看起来会以非常快的速度变得清晰。