【问题标题】:Image scrollview crashes图像滚动视图崩溃
【发布时间】:2012-05-11 16:37:29
【问题描述】:

我已经实现了一个带有分页功能的滚动视图,可以在整页的某些图像(图表)之间滚动(例如 iPhone 中安装的照片应用程序)。

我发现下面的代码使用了经典的 3 页解决方案(我对我的应用程序做了一些小的修改)但是,即使它“有效”,滚动似乎也很慢,而且通常在我滚动了一些图像之后应用程序崩溃。

我正在使用启用了 ARC 选项的 Xcode 4.2,并在 iPad 设备上进行了测试。 图片 (10 jpg) 为 2048x1539,每张平均尺寸为 200/250Kb。

有没有人可以帮我找出问题的原因?

谢谢, 科拉多

const int numImages = 10;
const float kPageWidth = 1024.0f;
const float kPageHeight = 768.0f;


- (void)viewDidLoad {
[super viewDidLoad];

    scroll.contentSize = CGSizeMake(kPageWidth * numImages, kPageHeight);
imageview1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kPageWidth, kPageHeight)];

imageview2 = [[UIImageView alloc] initWithFrame:CGRectMake(kPageWidth, 0, kPageWidth, kPageHeight)];    

imageview3 = [[UIImageView alloc] initWithFrame:CGRectMake(kPageWidth * 2, 0, kPageWidth, kPageHeight)];

scroll.contentOffset = CGPointMake(0, 0);

[imageview1 setImage:[UIImage imageNamed:@"grafico_0.jpg"]];
imageview1.contentMode = UIViewContentModeScaleAspectFit;
[imageview1 setTag:1];

imageview2.contentMode = UIViewContentModeScaleAspectFit;
[imageview2 setTag:2];

imageview3.contentMode = UIViewContentModeScaleAspectFit;
[imageview3 setTag:3];

[scroll addSubview:imageview1];
[scroll addSubview:imageview2];
[scroll addSubview:imageview3];        
}


- (void)scrollViewDidScroll:(UIScrollView*)scrollView {

const CGFloat currPos = scrollView.contentOffset.x;
const NSInteger selectedPage = lroundf(currPos * (1.0f / kPageWidth)); 
const NSInteger zone = 1 + (selectedPage % 3); 
const NSInteger nextPage = selectedPage + 1;
const NSInteger prevPage = selectedPage - 1;

/// Next page
if (nextPage < numImages)
{
    NSInteger nextViewTag = zone + 1;
    if (nextViewTag == 4)
        nextViewTag = 1;

    UIImageView* nextView = (UIImageView*)[scrollView viewWithTag:nextViewTag];      
    nextView.frame = (CGRect){.origin.x = nextPage * kPageHeight, .origin.y = 0.0f, kPageHeight, kPageWidth};

    NSString *str = [NSString stringWithFormat:@"grafico_%d.jpg", nextPage];
    UIImage* img = [UIImage imageNamed:str];
    nextView.image = img;
}


/// Prev page
if (prevPage >= 0)
{
    NSInteger prevViewTag = zone - 1;
    if (!prevViewTag)
        prevViewTag = 3;

    UIImageView* prevView = (UIImageView*)[scrollView viewWithTag:prevViewTag];      
    prevView.frame = (CGRect){.origin.x = prevPage * kPageHeight, .origin.y = 0.0f, kPageHeight, kPageWidth};

    NSString *str = [NSString stringWithFormat:@"grafico_%d.jpg", prevPage];
    UIImage* img = [UIImage imageNamed:str];
    prevView.image = img;
}

}

【问题讨论】:

    标签: ios uiscrollview uiimageview image-gallery


    【解决方案1】:

    您不应该使用imageNamed: 来加载大图像,因为该方法会缓存图像,并且应该只用于您在应用程序中多次使用的小图像(例如按钮图像等)。该方法因在与许多大图像一起使用时会导致内存问题而臭名昭著。

    改用imageWithContentsOfFile:。使用该方法加载图像可确保图像不会被缓存,并且在您不再使用该图像后释放内存。

    如果滚动看起来很缓慢,您可以使用 performSelectorInBackground 将图像的加载移动到后台线程:

    [self performSelectorInBackground:@selector(retrieveImageData:) withObject:imagePath];
    

    UIImage 的加载发生在这个方法中:

    - (void)retrieveImageData:(NSString *)imagePath {
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
      UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
      [self performSelectorOnMainThread:@selector(imageDataRetrieved:) withObject:image waitUntilDone:NO];
      [pool release];
    }
    

    以及将图像附加到主线程上的 UIImageView(UI 操作不得在后台线程上发生):

    - (void)imageDataRetrieved:(UIImage)*image {
      yourImageView.image = image;
    }
    

    【讨论】:

    • 谢谢,我用 imageWithContentsOfFile 替换了 ImageNamed,即使滚动仍然很慢,应用程序也不会崩溃。
    • 您是否按照我在回答中的描述加载图像? “滚动很慢”是什么意思?加载新图像时滚动停止一毫秒?或者您一次只能滚动一张图片?
    • 我的意思是图像之间的过渡似乎很缓慢。我将图像的大小减小到 1024x768 并且稍微好一点(2048x1539 (250Kb) 图像太大了吗?)。我也试图理解你的第二个解决方案,但我不太清楚(这是我的第一个应用程序!)。
    • 该图像大小应该不是问题。我使用上面提到的方法在我的应用程序中做同样的事情。在您的代码中,您将新图像加载到主线程上。这意味着整个应用程序(包括滚动动画)会停止,直到图像完全加载。这就是迟钝。我的方法是在后台加载图像。这意味着加载不会阻止整个应用程序。这就像在现实生活中的工厂中,您调用第二个工人来加载图像并在加载时将其返回给您,而不是您自己做所有事情。
    • 顺便说一句,我在答案中编辑了代码示例。方法名称不匹配。也许这增加了你的困惑;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多