简体   繁体   English

带有UIImageView,UIImage的UIScrollView

[英]UIScrollView with UIImageView, UIImage

I've read a lot of UIScrollView with UIImageView threads here or other googled pages. 我在这里或其他谷歌页面上阅读了很多带有UIImageView线程的UIScrollView。 But I still cannot get the problem I'm confronting. 但是我仍然无法解决我面临的问题。 I'm having a cold right now. 我现在感冒了。 Hope I can still make it clear, lol. 希望我仍然可以说清楚,大声笑。 Here is the problem: 这是问题所在:

I'm building one app which mainly uses UIScrollView to display a few images. 我正在构建一个主要使用UIScrollView来显示一些图像的应用程序。 Here the amount counts, not the size, which is averagely 100KB(I even converted PNG to jpg, not sure whether it helps or not). 这里的数量是计数,而不是大小,通常是100KB(我什至将PNG转换为jpg,不确定是否有帮助)。 With no more than 10 images, my app crashes with memory warning. 图像不超过10张,我的应用程序崩溃并显示内存警告。 This is the first time I encounter memory issue, which surprised me as the compiled app is less than 10MB. 这是我第一次遇到内存问题,因为已编译的应用程序小于10MB,这让我感到惊讶。

At the very beginning, I load all the images on launch, looping all names of image files and do 一开始,我会在启动时加载所有图像,循环所有图像文件名称,然后执行


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

If I'm right, I think after launch, all the images are in memory, right? 如果我是对的,我认为启动后所有图像都在内存中,对吗? But the funny thing here is, the app could launch without any problem(at most a level 1 memory warning). 但有趣的是,该应用程序可以启动而没有任何问题(最多为1级内存警告)。 After I scroll a few images, it crashed. 滚动几张图像后,它崩溃了。 I checked leaks for sure and also allocations. 我检查泄漏确定,也分配。 No leak and allocation almost had no change during scrolling. 在滚动过程中,没有泄漏和分配几乎没有变化。

So, is there something special done by imageNamed rather than cache? 那么,imageNamed是否有一些特殊的事情要做,而不是缓存?

And then, yes, I turned to lazy load. 然后,是的,我转向了延迟加载。

For fear of checking page and loading images on demand might jerk the scrolling(which was proved true), I used a thread which runs a loop to check offset of the scroll view and load/unload images. 由于担心检查页面和按需加载图像可能会导致滚动跳动(事实证明如此),我使用了一个线程,该线程运行一个循环来检查滚动视图的偏移量并加载/卸载图像。

I subclassed UIImageView by remembering the image name. 我通过记住图像名称对UIImageView进行了子类化。 It also contains loadImage and unloadImage which will be executed on that thread. 它还包含将在该线程上执行的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]; }

You can see the commented code that I've played with. 您可以看到我玩过的带注释的代码。

In unloadImage, if I write [self.image release] , then I get EXC_BAD_ACCESS, which is unexpected, as I think alloc and release are matched here. 在unloadImage中,如果我写[self.image release] ,则得到EXC_BAD_ACCESS,这是意外的,因为我认为alloc和release在这里匹配。

The app still crashes with no leak. 该应用程序仍然崩溃,没有泄漏。 The initWithContentsOfFile version even crashed earlier than imageNamed version, and made the scrolling not that smooth. initWithContentsOfFile版本甚至比imageNamed版本更早崩溃,并且滚动也不那么顺利。

I run the app on device. 我在设备上运行该应用程序。 By checking allocations, I found imageNamed version used much less memory than initWithContentsOfFile version, though they both crash. 通过检查分配,我发现imageNamed版本使用的内存比initWithContentsOfFile版本少得多,尽管它们都崩溃了。 Instruments also showed that the allocated images were 2,3 or 4, which indicated the lazy load did do his job. 仪器还显示分配的图像是2,3或4,这表明延迟加载确实完成了他的工作。

I checked PhotoScroller of WWDC2010, but I don't think it solvs my problem. 我检查了WWDC2010的PhotoScroller,但我认为它不能解决我的问题。 There is no zooming or huge picture involved. 不涉及缩放或巨大图片。

Anybody helps! 任何人都可以帮助! Thank you in advance. 先感谢您。

The crash log says nothing. 崩溃日志什么也没说。 The app crashes mostly after memory warning level = 2. And if run on simulator, there will be no problem. 该应用程序大部分在内存警告级别= 2后崩溃。如果在模拟器上运行,则不会有问题。

You can load all the images to an array. 您可以将所有图像加载到阵列。 And you can design a view having one image view and try the below code: 您可以设计一个具有一个图像视图的视图,然后尝试以下代码:

array name: examplearray and view name :exampleview 数组名称: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);
}

It doesn't matter which format do you use for your images. 图像使用哪种格式都没有关系。 They're converted to bitmaps when you display them. 当您显示它们时,它们将转换为位图。

I'd suggest to use the technique similar to that one which is used by UITableView (hide the image and free the memory it uses when it disappears from the screen and instantiate the image only when you need to show it). 我建议使用类似于UITableView的技术(隐藏图像并释放它从屏幕上消失时使用的内存,并仅在需要显示它时才实例化该图像)。

As an alternate way – if you need to show these images in a grid – you might take a look to a CATiledLayer. 作为一种替代方法-如果您需要在网格中显示这些图像-您可以看一下CATiledLayer。

Anyhow, loading all the images to the memory is not the best idea :) 无论如何,将所有图像加载到内存中并不是最好的主意:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM