0

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!!!

  • No memory warnings visible in the console? (level 1 and/or 2) – Till Aug 09 '12 at 15:59
  • 4
    It's probably not a good idea to alloc 200 UIImageView at once (I don't believe user can see all of them in the same screen right?), a much better approach is to use some kind of reusing mechanism. – Eyal Aug 09 '12 at 16:06

3 Answers3

1

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.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    Really thanks a lot for all your answer, I think I understand the problem now...and going to modify code soon... – user1156202 Aug 10 '12 at 12:45
  • I really appreciate your suggestion...and yes all the objects are in the dict because the pictures data is not static, anytime when user take a photo from his camera, new photo will be there...Do you think is a good way to keep them in persitent storage? But I think program need to read and modify the file if there is any changes in the local photo album. – user1156202 Aug 10 '12 at 12:50
  • @user1156202 Actually, the `ALAssetLibrary` is a perfect persistent storage itself. No need to resort to anything else. Just grab the `ALAsset` objects (which are nice and small) and, for those visible objects, you can grab the `thumbnail` property and use that for really fast response time. On my device, with 500+ images, I was even able to use `defaultRepresentation.fullScreenImage` (I wouldn't suggest that for the gallery of thumbnail images, but I was just testing the loadVisibleImages logic) to make sure it was correctly loading visible images and unloading offscreen ones. Works great. – Rob Aug 10 '12 at 20:06
0

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.

Jody Hagins
  • 27,943
  • 6
  • 58
  • 87
0

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!

timthetoolman
  • 4,613
  • 1
  • 22
  • 22