【问题标题】:UIScrollView with UIImageView, UIImageUIScrollView 与 UIImageView、UIImage
【发布时间】:2011-06-18 10:56:59
【问题描述】:

我已经阅读了很多带有 UIImageView 线程的 UIScrollView 或其他谷歌页面。但我仍然无法解决我面临的问题。我现在感冒了。希望我还能说清楚,大声笑。问题来了:

我正在构建一个应用程序,它主要使用 UIScrollView 来显示一些图像。这里是数量而不是大小,平均为 100KB(我什至将 PNG 转换为 jpg,不确定是否有帮助)。不超过 10 张图像,我的应用程序崩溃并出现内存警告。这是我第一次遇到内存问题,这让我很惊讶,因为编译的应用程序小于 10MB。

一开始,我在启动时加载所有图像,循环所有图像文件的名称并执行


    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imgName]];
    [scrollview addSubview:imageView];
    [imageView release];

如果我是对的,我认为发布后,所有图像都在内存中,对吧?但有趣的是,应用程序可以毫无问题地启动(最多 1 级内存警告)。滚动几张图片后,它崩溃了。我确实检查了泄漏以及分配。滚动过程中没有泄漏和分配几乎没有变化。

那么,imageNamed 比缓存做了什么特别的事情吗?

然后,是的,我转向延迟加载。

由于担心检查页面和按需加载图像可能会影响滚动(这被证明是正确的),我使用了一个线程来运行一个循环来检查滚动视图的偏移量和加载/卸载图像。

我通过记住图像名称来继承 UIImageView。它还包含将在该线程上执行的 loadImage 和 unloadImage。


- (void)loadImage {
    /if ([self.subviews count] == 0) {
        UIImageView iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:self.imageName]];
        [self performSelectorOnMainThread:@selector(renderImage:) withObject:iv waitUntilDone:NO];
        //[self addSubview:iv];
        [iv release];
    }*/

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];
}

}

// render image on main thread - (void)renderImage:(UIImage*)iv { //[self addSubview:iv]; self.image = iv; }

  • (void)unloadImage { self.image = nil; //[(UIView*)[self.subviews lastObject] removeFromSuperview]; }

你可以看到我玩过的注释代码。

在unloadImage中,如果我写[self.image release],那么我会得到EXC_BAD_ACCESS,这是出乎意料的,因为我认为alloc和release在这里是匹配的。

应用程序仍然崩溃,没有泄漏。 initWithContentsOfFile 版本甚至比 imageNamed 版本更早崩溃,并且滚动不那么流畅。

我在设备上运行应用程序。通过检查分配,我发现imageNamed 版本使用的内存比initWithContentsOfFile 版本少得多,尽管它们都崩溃了。 Instruments 还显示分配的图像是 2,3 或 4,这表明延迟加载确实起到了作用。

我检查了 WWDC2010 的 PhotoScroller,但我认为它不能解决我的问题。不涉及缩放或大图。

任何人都可以帮助!提前谢谢你。

【问题讨论】:

    标签: iphone ios uiscrollview uiimageview


    【解决方案1】:

    崩溃日志什么也没说。应用程序在内存警告级别 = 2 后崩溃。如果在模拟器上运行,则不会出现问题。

    【讨论】:

    • 我认为这可能与多线程有关。我会花更多时间玩这个。
    【解决方案2】:

    您可以将所有图像加载到一个数组中。您可以设计一个具有一个图像视图的视图并尝试以下代码:

    数组名: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);
    }
    

    【讨论】:

      【解决方案3】:

      您对图像使用哪种格式并不重要。当您显示它们时,它们会转换为位图。

      我建议使用类似于 UITableView 使用的技术(隐藏图像并在它从屏幕上消失时释放它使用的内存,并仅在需要显示时实例化图像)。

      作为另一种方式 - 如果您需要在网格中显示这些图像 - 您可以查看 CATiledLayer。

      无论如何,将所有图像加载到内存中并不是最好的主意:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-07
        • 2011-05-21
        • 1970-01-01
        • 2011-12-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多