Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memory warning when scroll the photo #36

Open
scorpiozj opened this issue Nov 9, 2011 · 14 comments
Open

memory warning when scroll the photo #36

scorpiozj opened this issue Nov 9, 2011 · 14 comments

Comments

@scorpiozj
Copy link

I touch the thumbnail to see the photo, and I scroll left/right.
After several times (about 10), it receives memory warning.
Continue to scroll and it crashes.
My photo is about 2M+ and has a size of 1600*2400 or so on.
I notice there is handle for memory in SDImageCache.m, but it seems that it doesn't work.

@rogowskimark
Copy link

In my app I have got the same situation. Is there a way I can track which images are loaded and which should be removed from memory? I have seen methods loadPhoto and unLoadPhoto, but that not seems to release memory. I have done tests in Instruments and it looks like when new image gets loaded memory from images which should be released is still taken. Any help for this situation would be appreciated.

@BonnyLin
Copy link

I have same problem.For this problem, it's "reuse".....
I keep photoViews_ for 3 views and reuse them.
This is my code, it's work for me...

in KTPhotoScrollViewController.m

  • (void)viewDidLoad {
    ......
    photoViews_ = [[NSMutableArray alloc] initWithCapacity:3];
    for (int i=0; i < 3; i++) {
    [photoViews_ addObject:[NSNull null]];
    }
    }

  • (void)loadPhoto:(NSInteger)index {
    ......
    NSInteger idx = index % 3;
    id currentPhotoView = [photoViews_ objectAtIndex:idx];
    if (NO == [currentPhotoView isKindOfClass:[KTPhotoView class]]) {
    // Load the photo view.
    ......
    [photoViews_ replaceObjectAtIndex:idx withObject:photoView];
    ......
    }
    else {
    // Turn off zooming.
    [currentPhotoView turnOffZoom];

    CGRect frame = [self frameForPageAtIndex:index];
    [currentPhotoView setFrame:frame];
    [currentPhotoView setIndex:index];
    // Set the photo image.
    if (dataSource_) {
        if ([dataSource_ respondsToSelector:@selector(imageAtIndex:photoView:)] == NO) {
            UIImage *image = [dataSource_ imageAtIndex:index];
            [currentPhotoView setImage:image];
        } else {
            [dataSource_ imageAtIndex:index photoView:currentPhotoView];
        }
    }
    
    [photoViews_ replaceObjectAtIndex:idx withObject:currentPhotoView];
    

    }
    }

  • (void)setCurrentIndex:(NSInteger)newIndex
    {
    currentIndex_ = newIndex;

    [self loadPhoto:currentIndex_ - 1];
    [self loadPhoto:currentIndex_];
    [self loadPhoto:currentIndex_ + 1];

    [self setTitleWithCurrentPhotoIndex];
    [self toggleNavButtons];
    }

In SDImageCache.m

Find [memCache setObject:image forKey:key];

if (memArray.count > 3) {
[cacheInQueue cancelAllOperations];

..... remeber remove object in memCache

            [memCache removeObjectForKey:_memKey];

}
[memCache setObject:image forKey:key];

@scorpiozj
Copy link
Author

BonnyLin, have you tried : if the photos have a large resolution?
I think the problem just like rogowskimark referred, the old image view is removed, but not released in memory. I guess it may mistakenly retained somewhere, But I can't find where it is.

@BonnyLin
Copy link

In my project, every photo was more than 1.5MB, but almost 2.0MB(like urs.)
and 800+ photos in every folder....(my project about read from wifi dvdrom.)

So i reuse KTPhotoView for 3 views(Performance not bad...huh)...and clear cache.
U can use 3 or 5 views in photoarray. (KTPhotoScrollViewController.m)

I think maybe your problem is too many PhotoView in photoarray.
I guess.^_^||

@scorpiozj
Copy link
Author

Thanks, it sounds great and I'll try it~

But I still want to know :
how to release the photo view, as you can see: although it has unload, the memory doesn't seem to release.

@BonnyLin
Copy link

  • (void)unloadPhoto:(NSInteger)index
    {
    if (index < 0 || index >= photoCount_) {
    return;
    }

    id currentPhotoView = [photoViews_ objectAtIndex:index];
    if ([currentPhotoView isKindOfClass:[KTPhotoView class]]) {
    [currentPhotoView removeFromSuperview]; <================Only remove from superview, but PhotoView->imageView_ not release or clear.... so memory still using...
    [photoViews_ replaceObjectAtIndex:index withObject:[NSNull null]];
    }
    }

@scorpiozj
Copy link
Author

So here:

[photoViews_ replaceObjectAtIndex:index withObject:[NSNull null]];

it will cause the the currentPhotoView to be released once, right?

I understand it like this:

  • (void)loadPhoto:(NSInteger)index
    {
    if (index < 0 || index >= photoCount_) {
    return;
    }

    id currentPhotoView = [photoViews_ objectAtIndex:index];
    if (NO == [currentPhotoView isKindOfClass:[KTPhotoView class]]) {
    // Load the photo view.
    CGRect frame = [self frameForPageAtIndex:index];
    KTPhotoView *photoView = [[KTPhotoView alloc] initWithFrame:frame];
    [photoView setScroller:self];
    [photoView setIndex:index];
    [photoView setBackgroundColor:[UIColor clearColor]];

    // Set the photo image.
    if (dataSource_) {
    if ([dataSource_ respondsToSelector:@selector(imageAtIndex:photoView:)] == NO) {
    UIImage *image = [dataSource_ imageAtIndex:index];
    [photoView setImage:image];
    } else {
    [dataSource_ imageAtIndex:index photoView:photoView];
    }
    }

    [scrollView_ addSubview:photoView];
    [photoViews_ replaceObjectAtIndex:index withObject:photoView];
    [photoView release];//---------------------- scrollView and photoVIew_ retain the photoView, right?
    } else {
    // Turn off zooming.
    [currentPhotoView turnOffZoom];
    }
    }

SO in unload: when currentPhotoView is removed, only photoViews_ retains it.
After [photoViews_ replaceObjectAtIndex:index withObject:[NSNull null]]; currentPhotoView should be released and its memory should be free by the pool.

Am I wrong?

@BonnyLin
Copy link

U can add function in KTPhotoView.m call -(void)releaseall and then set imageView_->image = nil and others..
then add [currentPhotoView releaseall]; before [currentPhotoView removeFromSuperview];
I tried, but when i read about 55 photos. i will recevie memory warning level=1 and quickly scroll to next, will recevice ImageIO:error message, then No.65+ photos will rotate wrong way, if i still scroll to next photo, about No.70+ (soon) will receive memory warning level=2 then crash....

Original code: 3x level1 => 3x4x imageio error => 4x5x level2 => crash.
Edited code: 5x level1 => 5x6x imageio error => 6x7x level2 => crash.

maybe i use wrong way to release memory...so i use my stupid way to resolve my problem...haha ^_^|||

Hope can help u.

[photoViews_ replaceObjectAtIndex:index withObject:photoView];
[photoView release]; <==========It's release photoView but u added into photoViews_...

photoViews_ will more and more...

then replace by [NSNull null]....
http://stackoverflow.com/questions/7743814/nsmutablearray-release-an-object-at-index

"the object that as released won't actually be freed unless the retain count goes to 0"

because we use NSMutableArray and give it a capacity count,
when array is almost full, it will (maybe) "copy" to double size array.
i guess .

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html

U can use "Xcode Profile" to listen, will find the memory change. I use "alloc" to check my code..

@yanfangjin
Copy link

How about this memory issue. I also have this problem. The issue is: when I browse the large photo slowly, the memory will increase and also be down to low level. But If quickly browse the large photo, the memory will increase quickly and receive the low memory and then crash.
I have already add the autoreleasepool.
@autoreleasepool {
[self loadPhoto:currentIndex_];
[self loadPhoto:currentIndex_ + 1];
[self loadPhoto:currentIndex_ - 1];
[self unloadPhoto:currentIndex_ + 2];
[self unloadPhoto:currentIndex_ - 2];
}
Is there any method to avoid the memory crash? I am also confuse the replaceObjectAtIndex:index can not release the large photo. Some other will retain the photo?

http://stackoverflow.com/questions/11462878/iphone-memory-heap-increase-for-uiimage

@scorpiozj
Copy link
Author

@yanfangjin I believe this lib is mainly for the small-size photos as UIImageView simply is not suitable for showing large-size image.

@yanfangjin
Copy link

@scorpiozj yes. I have check this issue many times, but I can not fixed the memory increase issue. Did you have some solution to resolve the large-size image browse and view project, such as the native gallery?

@scorpiozj
Copy link
Author

@yanfangjin in my opinion, resize the large image. In the native photo app, the photo is also resized. If you import a large image from iPhoto to iPhoto,you will see the image is compressed to a suitable size (you can send the photo from iPhone to test it). If you want to show originally large one, you should see CALayer.

@yanfangjin
Copy link

@scorpiozj , actuarially, I only use the max photo size is 1600*1200. But I will decode from the 8M photo from captured image in iPhone4S. Is there any sample code about the CALayer for large image browser?

@scorpiozj
Copy link
Author

@yanfangjin ,yes you can search in developer.apple.com. there are several samples

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants