The reason for the large allocation of memory (memory leak?) When reading UIImage from the camera roll

I am trying to change FGallery (https://github.com/gdavis/FGallery-iPhone). I need this to read images from a camera roll, but I get a memory leak.

Old code (path is the location of the file):

@autoreleasepool { NSString *path = [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] bundlePath],_thumbUrl]; _thumbnail = [UIImage imageWithContentsOfFile:path]; _hasThumbLoaded = YES; _isThumbLoading = NO; [self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil waitUntilDone:YES]; } 

My code (path is the URL of the library approval):

 @autoreleasepool { ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) { ALAssetRepresentation *rep = [myasset defaultRepresentation]; CGImageRef iref = [rep fullResolutionImage]; if (iref) { _thumbnail = [UIImage imageWithCGImage:iref]; _hasThumbLoaded = YES; _isThumbLoading = NO; [self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil waitUntilDone:YES]; } }; ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror) { NSLog(@"booya, cant get image - %@",[myerror localizedDescription]); }; NSURL *asseturl = [NSURL URLWithString:_thumbUrl]; [assetslibrary assetForURL:asseturl resultBlock:resultblock failureBlock:failureblock]; } } 

For the same images, I get a large memory allocation (-didReceiveMemoryWarning) that breaks the program in my code, but not when using the source code.

Any ideas why?

PS I use ARC, and made an automatic transition for FGallery. It works great for local application images, but as said, I can't get it to work with camera images.

change 1: program crash

+1
source share
4 answers

I think I get it. "ALAssetsLibraryAssetForURLResultBlock resultblock" is running in another thread. and therefore "@autoreleasepool" does not apply to it. (each branch has its own pool of autoresists). therefore, the amount of memory is much higher due to the many "auto-implemented" distributions (images). adding "@autoreleasepool" inside the block stopped crashes and large memory allocations.

:

 ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) { @autoreleasepool { ALAssetRepresentation *rep = [myasset defaultRepresentation]; CGImageRef iref = [rep fullResolutionImage]; if (iref) { _thumbnail = [UIImage imageWithCGImage:iref]; _hasThumbLoaded = YES; _isThumbLoading = NO; [self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil waitUntilDone:YES]; } } }; 

Thanks to all who responded.

+6
source

If there is no need for full resolution, you will probably be better off using:

 CGImageRef iref = [rep fullScreenImage]; 

This call returns a CGImage of a view that is suitable for displaying a full screen, and not the largest, best view available, not adjusted in any way.

This will save a lot of memory.

+4
source

Getting a memory warning (-didReceiveMemoryWarning) is not the same as a memory leak. It just means that you have a lot of allocated memory, and this puts pressure on the system, where the OS interprets this as a potential problem that could happen in the near future.

A memory leak occurs when you have unregistered objects that have not been released. You can use the compiler analysis tool to see where potential leaks exist. This will not find them all, so you can use the tools to see where others may be. But until you test these tools, you cannot say for sure that you have a leak that is not obvious when you look at the code.

You did not mention if your code is crashing, but if so, this is not necessarily a memory leak. This can happen when the OS decides that something needs to be removed to reduce the pressure in the memory.

UPDATE

Show code for class ALAssetRepresentation. You cannot release something there.

0
source

As Picciano said in his post, if possible, you should use the [rep fullScreenImage]; call [rep fullScreenImage]; instead of requesting a full-sized image. This will save a lot of space. However, in my case this was not possible because I need to send a higher resolution image to an external server later. What you can do is use the scale to change it as much as possible:

 CGFloat originalRatio = assetRepresentation.dimensions.width / assetRepresentation.dimensions.height; CGFloat wantedRatio = maxSize.width / maxSize.height; CGFloat scale = 1; if (originalRatio < wantedRatio) { scale = maxSize.height / assetRepresentation.dimensions.height; } else { scale = maxSize.width / assetRepresentation.dimensions.width; } CGImageRef ref = [assetRepresentation fullResolutionImage]; UIImage *image = [UIImage imageWithCGImage:ref scale:scale orientation:orientation]; 

That it basically determines the size of the scalable image (determined by maxSize ). This allowed us to avoid memory leaks.

0
source

Source: https://habr.com/ru/post/1208146/


All Articles