Help me understand leaks on this code: [duplicate] - iphone

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to release an object declared into a method and passed to another method?
Can you help me fix leaks in this code:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
UIImage *payload = [[UIImage alloc] initWithData:self.activeDownload];
UIImage *picture = [[UIImage alloc] init];
if (payload.size.width != kAppIconHeight && payload.size.height != kAppIconHeight)
{
CGSize itemSize = CGSizeMake(kAppIconHeight, kAppIconHeight);
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[payload drawInRect:imageRect];
picture = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
else
{
picture = payload;
}
self.activeDownload = nil;
[payload release];
self.imageConnection = nil;
[delegate ThumbDidLoad:self.indexPathInTableView Image:[picture autorelease]];
}
Thx for helping,
Stephane

When you set picture = UIGraphicsGetImageFromCurrentImageContext() in your if statement or picture = payload in your else statement, you are loosing the pointer to the previously allocated UIImage you assigned in picture in the first lines, but you never released it.
You shouldn't alloc+init a new UIImage for picture, as you never use it and assign a new value to this variable later... but never used and released the previously allocated one.

UIImage *picture = [[UIImage alloc] init]; and picture = UIGraphicsGetImageFromCurrentImageContext();
You should not initialize picture at the beginning of the code. UIGraphicsGetImageFromCurrentImageContext returns a already initialized UIImage (autoreleased).
UIImage *payload = [[UIImage alloc] initWithData:self.activeDownload];, picture = payload;, [payload release];.
You should use [payload autorelease] instead, otherwise you're releasing the image without ever using it.
[delegate ThumbDidLoad:self.indexPathInTableView Image:[picture autorelease]];
You should remove [picture autorelease] and just use picture.
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
UIImage *payload = [[UIImage alloc] initWithData:self.activeDownload];
UIImage *picture;
if (payload.size.width != kAppIconHeight && payload.size.height != kAppIconHeight)
{
CGSize itemSize = CGSizeMake(kAppIconHeight, kAppIconHeight);
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[payload drawInRect:imageRect];
picture = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
else
{
picture = payload;
}
[payload autorelease];
self.activeDownload = nil;
self.imageConnection = nil;
[delegate ThumbDidLoad:self.indexPathInTableView Image:picture];
}

Related

Create Array in cellForRowInIndexPath

I'm trying to save an array of images that I retrieve asynchronously in the cellForRowInIndexPath method of the UITableViewController.
Unfortunately, the array is not fully populated or in incorrect order.
The code within my tableview:cellForRowAtIndexPath method is:
// populate the cell's image
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
NSURL *url = [NSURL URLWithString:[newsModel url]];
NSData *data = [NSData dataWithContentsOfURL:url];
img = [[UIImage alloc] initWithData:data] ;
[imageArray insertObject:img atIndex:[indexPath row]];
dispatch_sync(dispatch_get_main_queue(), ^{
// make image standard size
CGSize imageSize = CGSizeMake(40, 40);
UIGraphicsBeginImageContext(imageSize);
CGRect imageRect = CGRectMake(0.0, 0.0, imageSize.width, imageSize.height);
[img drawInRect:imageRect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[cell setNeedsLayout];
});
});
Both the imageArray (NSMutableArray) and img (UIImage) are of type __bool.
Thanks in advance for your help.
Try to store into dictionary with key inplace of array because no chances to duplication after that insert into array using AllValue of dictionary
For ex:
imageArray =[[dict allValues]mutableCopy];
NSMutableDictionary *dict=[[NSMutableDictionary alloc]init];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
NSURL *url = [NSURL URLWithString:[newsModel url]];
NSData *data = [NSData dataWithContentsOfURL:url];
img = [[UIImage alloc] initWithData:data] ;
[dict setObject:img forKey:indexPath.row]
dispatch_sync(dispatch_get_main_queue(), ^{
// make image standard size
CGSize imageSize = CGSizeMake(40, 40);
UIGraphicsBeginImageContext(imageSize);
CGRect imageRect = CGRectMake(0.0, 0.0, imageSize.width, imageSize.height);
[img drawInRect:imageRect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[cell setNeedsLayout];
});
});
imageArray =[[dict allValues]mutableCopy];
Don't try to modify the cell after the download has completed, you don't know if it's been reused. Just save the image and then ask the table view to reloadData (ensure you ask for the reload on the main thread).

Adding a UIMapView Thumbnail with Pin

I've been trying to implement a UIMapView Icon like the one in this picture. Does anybody know how this app is creating that thumbnail?
Edit
Attempting to implement this with the following code:
CLLocationCoordinate2D restaurantLocation = CLLocationCoordinate2DMake(Latitude, Longitude);
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(restaurantLocation, 1000, 1000);
_mapView.region = region;
_mapView.hidden = NO;
_annotation = [[MKPointAnnotation alloc] init];
_annotation.coordinate = restaurantLocation;
//annotation.title = _restaurantInformation
[_mapView addAnnotation:_annotation];
UIGraphicsBeginImageContext(_mapView.frame.size);
[_mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *mapImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGSize newSize;
newSize.width = 50; // any width u want
newSize.height= 80; // any height u want
UIGraphicsBeginImageContext(newSize);
[mapImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
_mapThumbnail.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Annotation in Mapview with location should be in centre. Now
UIGraphicsBeginImageContext(mapView.frame.size);
[mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *mapImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
For creating thumbnail of mapImage resize according
CGSize newSize;
newSize.width = 50; // any width you want
newSize.height= 80; // any height you want
UIGraphicsBeginImageContext(newSize);
[mapImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* thumbnail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Another Way is
You can try Google Static Maps API
Here's sample code
NSString *urlString = #"http://maps.googleapis.com/maps/api/staticmap?center=Berkeley,CA&zoom=14&size=200x200&sensor=false";
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
UIImage *thumbnail= [UIImage imageWithData:data];
[yourImageView setImage:thumbnail];
Through this you can get static image based on your coordinates.
This code for showing thumbnail of particular location and its working for me
NSString *staticMapUrl = [NSString stringWithFormat:#"http://maps.google.com/maps/api/staticmap?markers=color:red|%f,%f&%#&sensor=true",lat, log,#"zoom=10&size=114x116"];
NSURL *mapUrl = [NSURL URLWithString:[staticMapUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL:mapUrl]];
[imgViewClue setImage:image];

Load qr code from url and display as image view

As the title says I'm trying to take a qr code like this - http://chart.apis.google.com/chart?cht=qr&chs=200x200&chl=044779-A55W6UZD&chld=H|0 and display it as a UIImageview. I've searched but couldn't find an answer anywhere. Please help.
I've tried this but it doesn't seem to work
NSData *receivedData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [[UIImage alloc] initWithData:receivedData];
UIImageView * myImageView = [[UIImageView alloc] initWithImage:image];
myImageView.frame = CGRectMake(20, 160, 200, 200);
[self.view addSubview:myImageView];
Try encoding the url like this and then use encodedUrl in the rest of the code:
NSString* encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
You should also remember to release the objects you created, otherwise you leak memory.
NSData* receivedData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:encodedUrl]];
UIImage* image = [[UIImage alloc] initWithData:receivedData];
UIImageView* myImageView = [[UIImageView alloc] initWithImage:image];
myImageView.frame = CGRectMake(20, 160, image.size.width, image.size.height;
[self.view addSubview:myImageView];
[receivedData release];
[image release];
[myImageView release];

How to release an object declared into a method and passed to another method?

Any idea on how to release the UIImage object picture in this case:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
UIImage *payload = [[UIImage alloc] initWithData:self.activeDownload];
UIImage *picture = [[UIImage alloc] init];
if (payload.size.width != kAppIconHeight && payload.size.height != kAppIconHeight)
{
CGSize itemSize = CGSizeMake(kAppIconHeight, kAppIconHeight);
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[payload drawInRect:imageRect];
picture = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
else
{
picture = payload;
}
self.activeDownload = nil;
[payload release];
self.imageConnection = nil;
[delegate ThumbDidLoad:self.indexPathInTableView Image:picture];
}
Thx for helping,
Stephane
You need to make it autorelease
UIImage *picture = [[[UIImage alloc] init]autorelease];
I'm having a hard time understanding why your "picture" variable has an alloc init at all. I agree with earlier answers to use autorelease, but perhaps something more like:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
UIImage *payload = [UIImage imageWithData:self.activeDownload];
UIImage *picture = nil;
if (payload.size.width != kAppIconHeight && payload.size.height != kAppIconHeight)
{
CGSize itemSize = CGSizeMake(kAppIconHeight, kAppIconHeight);
UIGraphicsBeginImageContext(itemSize);
CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
[payload drawInRect:imageRect];
picture = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
else
{
picture = payload;
}
self.activeDownload = nil;
self.imageConnection = nil;
[delegate ThumbDidLoad:self.indexPathInTableView Image:picture];
}
Couple changes above:
1. UIImage *payload = [UIImage imageWithData:self.activeDownload];. Changed this assignment to an autoreleased object since picture may be assigned to it. Note that the if clause assigns picture to an autoreleased object, so the else clause should too and now it does since payload is now an autoreleased object.
2. UIImage *picture = nil; instead of UIImage *picture = [[UIImage alloc] init];. I did this since the picture assignment is NEVER used, so nil is actually valid since it will definitely be assigned in either the if or else clause.
3. No need for [payload release] now that payload is autoreleased.
I think:
[delegate ThumbDidLoad:self.indexPathInTableView Image:[picture autorelease]];
or
[delegate ThumbDidLoad:self.indexPathInTableView Image:picture];
[picture release];
But I see two problems in your code - leaks at picture = payload; and [payload release]; can release image, that is also indicated by the picture

iPhone: Memory used by images is not freed

I have this code below that loads images from the web.
Those images are shown after clicking on a table cell, and they are reloaded every time the table cell is clicked.
The point is that analyzing the memory allocation with "Instruments", when I go back from the detail view to the table, the memory occupied from the images is not freed.
Does anyone have any suggestion?
I, of course, do all the release of the case... but it seems to don't help.
NSError *error = nil;
UIImage *img = nil;
NSString *myurl = [IMG_SERVER_URL stringByAppendingString: tmp_link.url];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSData *imageData = nil;
if(myurl!=nil){
imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:myurl] options:nil error:&error];
if (error == 0) {
img = [[UIImage alloc] initWithData:imageData];
}
}
[imageData release]; imageData = nil;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(targetWidth*i, 0, targetWidth, targetHeight)];
imageView.image = img;
imageView.contentMode = UIViewContentModeScaleAspectFit;
[img release];
[....some code....]
[imageView release];
I think "imageView.image = img" increases the reference count on the image object. If I'm right the allocated memory will not get freed as long as you don't release the imageView.