user1156202
user1156202

Reputation: 25

Program crashes when loading 200+ subview images in the UIScrollView

I am developing a similar program like Photos in the iPhone using ALAssetLibrary. I am trying to load the images in a scrollview. Everything works fine when the album has small amount of pictures. But when I trying to load the album with 200+ photos, my program ended without any error message. Anyone know this program? Here is my code for loading scroll view:

- (void)loadScrollView
{
for (UIView *v in [scrollview subviews]) {
    [v removeFromSuperview];
}

CGRect scrollFrame = [self frameForPagingScrollView];
scrollview = [[UIScrollView alloc] initWithFrame:scrollFrame];

CGRect workingFrame = scrollview.frame;
workingFrame.origin.y = 0;

photoCount = [info count];
for(NSDictionary *dict in info) {
    UIImageView *imageview = [[UIImageView alloc] initWithImage:[dict objectForKey:UIImagePickerControllerOriginalImage]];
    [imageview setContentMode:UIViewContentModeScaleAspectFit];
    imageview.frame = workingFrame;

    [scrollview addSubview:imageview];
    [imageview release];
    [scrollview setPagingEnabled:YES];
    [scrollview setDelegate:self];
    [scrollview setAutoresizesSubviews:YES];
    [scrollview setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
    [scrollview setShowsVerticalScrollIndicator:NO];
    [scrollview setShowsHorizontalScrollIndicator:NO];

    workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;

}

[self setScrollViewContentSize];
[[self view] addSubview:scrollview];
}

Thanks a lot in advance!!!

Upvotes: 0

Views: 1117

Answers (3)

timthetoolman
timthetoolman

Reputation: 4623

why not use UICollectionView and UICollectionViewController classes? UICollectionViewController reference here

sample code here.

Your images will end up being instances of UICollectionViewCell. The data source and delegate protocol methods are similar to the UITableView methods. i.e. they provide a mechanism where the UICollectionViewController will reuse the UICollectionViewCells.

The benefit of using these classes is that they are used similarly to UITableViewControllers and they assist you with the memory pressure issues that you are having.

good luck!

Upvotes: 0

Rob
Rob

Reputation: 437872

I personally put all of my UIImageView objects on my UIScrollView, but only set the image property for them for those that are currently visible (and clear the image property for those that are no longer visible). If you have thousands of images, perhaps even that is too wasteful (perhaps you don't even want to keep the UIImageView objects, even without their image property set, around), but if you're dealing with hundreds, I find it is a nice easy solution, addressing the key problem of the memory consumed by the UIImage objects:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.scrollView.delegate = self;

    // all of my other viewDidLoad stuff...
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self loadVisibleImages];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    [self loadVisibleImages];
}

- (void)loadVisibleImages
{
    CGPoint contentOffset = self.scrollView.contentOffset;
    CGRect  contentFrame  = self.scrollView.bounds;
    contentFrame.origin = contentOffset;

    for (UIImageView *imageView in _imageViews) // _imageViews is (obviously) my array of images 
    {
        if (CGRectIntersectsRect(contentFrame, imageView.frame))
        {
            imageView.image = ... // set the image property
        }
        else
        {
            imageView.image = nil;
        }
    }
}

This is a snippet from some code that's doing a bunch of other stuff, so clearly your implementation will differ significantly, but it shows how you can use scrollViewDidScroll to determine what images are visible and load/unload images appropriately. You could probably alter further if you want to also remove/add the UIImageView objects, too, but clearly the logic of "is this imageview visible" would have to be changed, rather than leveraging the frame of all of the UIImageView objects.

I'm not sure if I'm reading your code right, but do you also have all of your UIImage objects sitting in a dictionary, too? That's pretty extravagant use of memory, itself. I usually keep the actual images in some persistent store (e.g. I use Documents folder, though you could use Core Data or SQLite, though the latter two impose a significant performance hit for large images). The only images I keep in memory are the ones actively used by the UI and I'll use a NSCache object to keep a few around for performance reasons, but I otherwise pull them from persistent storage, not active memory.

Upvotes: 1

Jody Hagins
Jody Hagins

Reputation: 28409

You should use scroll view delegation to determine which images would be showing on the screen at the current time, and only have those loaded in memory.

Also, if you are displaying a much smaller than the actual image size, you should resize the image and use the smaller image.

Upvotes: 0

Related Questions