KTPhotoBrowser icon indicating copy to clipboard operation
KTPhotoBrowser copied to clipboard

memory warning when scroll the photo

Open scorpiozj opened this issue 13 years ago • 14 comments

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.

scorpiozj avatar Nov 09 '11 03:11 scorpiozj

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.

rogowskimark avatar Apr 02 '12 20:04 rogowskimark

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

BonnyLin avatar May 10 '12 00:05 BonnyLin

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.

scorpiozj avatar May 11 '12 06:05 scorpiozj

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.^_^||

BonnyLin avatar May 11 '12 07:05 BonnyLin

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.

scorpiozj avatar May 11 '12 08:05 scorpiozj

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

BonnyLin avatar May 11 '12 08:05 BonnyLin

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?

scorpiozj avatar May 11 '12 08:05 scorpiozj

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 => 3x~4x imageio error => 4x~5x level2 => crash. Edited code: 5x level1 => 5x~6x imageio error => 6x~7x 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..

BonnyLin avatar May 11 '12 08:05 BonnyLin

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

yanfangjin avatar Jul 13 '12 01:07 yanfangjin

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

scorpiozj avatar Jul 14 '12 13:07 scorpiozj

@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?

yanfangjin avatar Jul 18 '12 15:07 yanfangjin

@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.

scorpiozj avatar Jul 19 '12 01:07 scorpiozj

@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?

yanfangjin avatar Jul 23 '12 00:07 yanfangjin

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

scorpiozj avatar Jul 23 '12 05:07 scorpiozj