Releasing an image from memory - objective-c

I recently started to learn objective c and I'm making an application based on tableView, imageview and scrollView.
In tableview you press a button and the application pushes to scrollview where there's an image inside imageview. I get a problem when I tried releasing a memory from imageview (the image I loaded when pressing the button). The problem is, that the image I previously loaded is still there.
Here's the code I've got:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *headTitle = [[listContent objectAtIndex:indexPath.row] objectForKey:kItemTitleKey];
if ([headTitle isEqualToString:#"Differentialekvationer"]){
leafViewController.title = headTitle;
[[self navigationController] pushViewController:leafViewController animated:YES];
NSString *fullpath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:#"/c.png"];
UIImage *imageToLoad = [UIImage imageWithContentsOfFile:fullpath];
leafViewController.myImageView = [[UIImageView alloc] initWithImage:imageToLoad];
leafViewController.myScrollView = [[UIScrollView alloc] initWithFrame:leafViewController.view.bounds];
[leafViewController.myScrollView addSubview:leafViewController.myImageView];
leafViewController.myScrollView.contentSize = leafViewController.myImageView.bounds.size;
[leafViewController.view addSubview:leafViewController.myScrollView];
leafViewController.myScrollView.bounces = NO;
}else if ([headTitle isEqualToString:#"Gränsvärden"]){
leafViewController.title = headTitle;
[[self navigationController] pushViewController:leafViewController animated:YES];
NSString *fullpath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:#"/e.png"];
UIImage *imageToLoad = [UIImage imageWithContentsOfFile:fullpath];
leafViewController.myImageView = [[UIImageView alloc] initWithImage:imageToLoad];
leafViewController.myScrollView = [[UIScrollView alloc] initWithFrame:leafViewController.view.bounds];
[leafViewController.myScrollView addSubview:leafViewController.myImageView];
leafViewController.myScrollView.contentSize = leafViewController.myImageView.bounds.size;
[leafViewController.view addSubview:leafViewController.myScrollView];
leafViewController.myScrollView.bounces = NO;
}
and i tried to free the memory basically with everyting
-(void)viewDidDisappear{
leafViewController.myImageView.image = nil;
leafViewController.myScrollView = nil;
leafViewController.view = nil;
[leafViewController.myImageView release];}
I don't know what to look for and where the problem lies. Help would be much appreciated :).
P.S. Please note that I've been learning objective c for 4 days now so I'm a newbie

Related

cell label text changes on selection after scroll

I am having an issue with tableview cells that are created from 2 different prototype cells. I add my own labels and images to them.
They load fine, but after i scroll in the tableview, and then select a cell, the labels from other cells are getting added to the labels already present in the cell.
I've read about similar issues people are having but none address the fact that it only occurs on selection.
I have tried adding if (cell == nil){}; but that has no effect.
My cellForRowAtIndexPath is as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"NDSClassSubMenuViewController cellForRowAtIndexPath: running...");
NDSClassAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSDictionary *childNodes = [appDelegate.children objectAtIndex:0];
NSString *multicellstat = [childNodes objectForKey:#"#CELLTYPE"];
NSLog(#"Multicellstat %#", multicellstat);
NSLog(#"TESTING CHILD %#", childNodes);
//ONLY LOADING SUB MENU OPTIONS
NSString *cellType;
if (multicellstat == NULL){
NSLog(#"cellForRowAtIndexPath: #CellType == multicell. Making multicell.");
cellType = #"SegueCellSubmenu";
}else {
NSLog(#"cellForRowAtIndexPath: children variable is NOT NULL. Making MenuCell.");
cellType = #"SegueCellMulti";
}
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellType forIndexPath:indexPath];
if (multicellstat == NULL){
NSLog(#"Not adding picture.");
}else {
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//this will start the image loading in bg
dispatch_async(concurrentQueue, ^{
UIView *blackBG = [[UIView alloc] initWithFrame:CGRectMake(5, 5, 60, 60)];
blackBG.backgroundColor = [UIColor grayColor];
NSURL *imageURL = [NSURL URLWithString:[childNodes objectForKey:#"#THUMBNAIL"]];
NSData *data = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:data];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(0, 0, 60, 60);
int borderWidth = 1;
imageView.frame = CGRectMake(borderWidth, borderWidth, blackBG.frame.size.width-borderWidth*2, blackBG.frame.size.height-borderWidth*2);
dispatch_async(dispatch_get_main_queue(), ^{
[cell addSubview:blackBG];
[blackBG addSubview:imageView];
});
});
}
//NSDictionary *tweet = [[[[appDelegate.menuItems objectForKey:#"Table"] objectForKey:#"Parent"]objectAtIndex:indexPath.row] objectForKey:#"Child"];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(70, 10, 210, 30)];
UILabel *detailText = [[UILabel alloc] initWithFrame:CGRectMake(70, 35, 210, 30)];
[cell.contentView addSubview:label];
[cell.contentView addSubview:detailText];
NSString *text = [[appDelegate.children objectAtIndex:indexPath.row] objectForKey:#"#MENUDESC"];
NSString *name = [[appDelegate.children objectAtIndex:indexPath.row] objectForKey:#"#MENUDESC"];
//NSLog(#"cellForRowAtIndexPath MENU ITEMS %#", text);
//Title label
label.text = NULL;
label.text = text;
[label setFont: [UIFont fontWithName:#"Arial" size:16.0]];
//Detail label
detailText.text = NULL;
detailText.text = name;
[detailText setFont: [UIFont fontWithName:#"Arial" size:12.0]];
//detailText.textColor = [UIColor colorWithRed:186.0/255.0 green:186.0/255.0 blue:186.0/255.0 alpha:1];
detailText.textColor = [UIColor grayColor];
//cell.textLabel.text = text;
//cell.detailTextLabel.text = [NSString stringWithFormat:#"by %#", name];
NSLog(#"Creating submenu item: %#", text);
NSLog(#"NDSClassSubMenuViewController: cellForRowAtIndexPath: finished.");
return cell;
}
Anyone know how I can solve this?
The key issue is that the code running synch should not assume that the cell it's modifying after the image request completes is the same cell (at the same indexPath) as when the image request began.
The correct recipe is like this:
use a cached result if we have one (so we don't do web requests every time we scroll), otherwise make an asynch request.
when the request completes, cache the result
use the original indexPath to determine if the cell is still visible. if it is, reload that indexPath. the newly cached result will now be available in cellForRowAtIndexPath.
Here's a snippet of code that describes how to correctly update at table after an asynch request. In your cellForRowAtIndexPath, check for a cached response before calling this:
// in cellForRowAtIndexPath:
NSString *urlString = [childNodes objectForKey:#"#THUMBNAIL"]
NSURL *imageURL = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
if (!cachedResponse) {
// we don't find this image/request in the cache, call asynch load
[self asynchLoad:urlString forIndexPath:indexPath];
} else {
// we got this image already, update the cell
UIImage *image = [UIImage imageWithData:cachedResponse.data];
// set the cell's UIImageView subview image to image
}
Here we load the image at urlString, cache the result, and then reload the indexPath after the load if it's still visible after the request completes:
- (void)asynchLoad:(NSString *)urlString forIndexPath:(NSIndexPath *)indexPath {
NSURL *imageURL = [NSURL URLWithString:[childNodes objectForKey:#"#THUMBNAIL"]];
NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error) {
// cache the response
NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:data];
[[NSURLCache sharedURLCache] storeCachedResponse:cachedResponse forRequest:self];
// important part - we make no assumption about the state of the table at this point
// find out if our original index path is visible, then update it, taking
// advantage of the cached image (and a bonus option row animation)
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
if ([visiblePaths containsObject:indexPath]) {
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation: UITableViewRowAnimationFade];
// because we cached the image, cellForRow... will see it and run fast
}
}
}];
}
I solved the problem by creating my own custom cell class and using storyboard to set the layout.

Can not adjust UIPopupController to display images

In my application (code listed below), I use a popover to display a series of colors that the user can choose. These colors are used for the color of the drawing they are completing above. I am trying to modify the popover to work the same way, except for this time I would want to display images (the images are saved in the application's documents folder as png files) instead of blocks of color. Listed below is the working code for the color selector popover. ColorGrid is a UIview which contains an NSArray Colors, as well as two NSUIntegers columnCount and rowCount. I have tried to replace the items in the colors array with UIImages of the png files, as well as UIImageViews but I have not been able to get a successful result (or a compilable one). Listed below is the working code. Could anyone show me how I can change the UIColor items to the images to show them in the grid?
- (IBAction)popoverStrokeColor:(id)sender {
StrokeColorController *scc = [[[StrokeColorController alloc] initWithNibName:#"SelectColorController" bundle:nil] autorelease];
scc.selectedColor = self.strokeColor;
[self doPopoverSelectColorController:scc sender:sender];
}
- (void)doPopoverSelectColorController:(SelectColorController*)scc sender:(id)sender {
[self setupNewPopoverControllerForViewController:scc];
scc.container = self.currentPopover;
self.currentPopover.popoverContentSize = scc.view.frame.size;
scc.colorGrid.columnCount = 2;
scc.colorGrid.rowCount = 3;
scc.colorGrid.colors = [NSArray arrayWithObjects:
//put the following below back in after testing
[UIColor blackColor],
[UIColor blueColor],
[UIColor redColor],
[UIColor greenColor],
[UIColor yellowColor],
[UIColor orangeColor],
//[UIColor purpleColor],
// [UIColor brownColor],
// [UIColor whiteColor],
// [UIColor lightGrayColor],
//[UIColor cyanColor],
//[UIColor magentaColor],
nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(colorSelectionDone:) name:ColorSelectionDone object:scc];
[self.currentPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; //displays the popover and anchors it to the button
}
Thanks for your help. I am new to objective-c.
edit - heres the function with my attempt to insert the images instead of the colors
- (void)doPopoverSelectColorController:(SelectColorController*)scc sender:(id)sender {
[self setupNewPopoverControllerForViewController:scc];
scc.container = self.currentPopover;
self.currentPopover.popoverContentSize = scc.view.frame.size;
// these have to be set after the view is already loaded (which happened
// a couple of lines ago, thanks to scc.view...
scc.colorGrid.columnCount = 2;
scc.colorGrid.rowCount = 3;
//here we need to get the UIImage items to try to put in the array.
NSArray *pathforsave = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [pathforsave objectAtIndex:0];
//here we need to add the file extension onto the file name before we add the name to the path
//[fileName appendString:#".hmat"];
NSString *strFile = [documentDirectory stringByAppendingPathComponent:#"test.png"];
NSString *strFile1 = [documentDirectory stringByAppendingPathComponent:#"test1.png"];
NSString *strFile2 = [documentDirectory stringByAppendingPathComponent:#"test2.png"];
NSString *strFile3 = [documentDirectory stringByAppendingPathComponent:#"test3.png"];
NSString *strFile4 = [documentDirectory stringByAppendingPathComponent:#"test4.png"];
NSString *strFile5 = [documentDirectory stringByAppendingPathComponent:#"test5.png"];
//now for the Images
UIImage *image = [ UIImage imageWithContentsOfFile: strFile];
UIImage *image1 = [ UIImage imageWithContentsOfFile: strFile1];
UIImage *image2 = [ UIImage imageWithContentsOfFile: strFile2];
UIImage *image3 = [ UIImage imageWithContentsOfFile: strFile3];
UIImage *image4 = [ UIImage imageWithContentsOfFile: strFile4];
UIImage *image5 = [ UIImage imageWithContentsOfFile: strFile5];
UIImageView *imageview = [[[UIImageView alloc] initWithImage:image] autorelease];
[self.view addSubview:imageview];
UIImageView *imageview1 = [[[UIImageView alloc] initWithImage:image1] autorelease];
[self.view addSubview:imageview1];
UIImageView *imageview2 = [[[UIImageView alloc] initWithImage:image2] autorelease];
[self.view addSubview:imageview2];
UIImageView *imageview3 = [[[UIImageView alloc] initWithImage:image3] autorelease];
[self.view addSubview:imageview3];
UIImageView *imageview4 = [[[UIImageView alloc] initWithImage:image4] autorelease];
[self.view addSubview:imageview4];
UIImageView *imageview5 = [[[UIImageView alloc] initWithImage:image5] autorelease];
[self.view addSubview:imageview5];
imageview.image = image;
imageview1.image = image1;
imageview2.image = image2;
imageview3.image = image3;
imageview4.image = image4;
imageview5.image = image5;
scc.colorGrid.colors = [NSArray arrayWithObjects:
// When attempting to add the images like this - get the error identified expected
// after the e in image, at the end bracket. Putting a * does nothing to change the error
[image],
// When adding one of the Imageviews, i get the same error as above
//below is how I attempted to add it
[imageView],
//
nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(colorSelectionDone:) name:ColorSelectionDone object:scc];
[self.currentPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; //displays the popover and anchors it to the button
}
Remove your square brackets around image and/or imageView :
scc.colorGrid.colors = [NSArray arrayWithObjects:
// Not : [image] but
image,
// or
imageView,
// Not : [imageView],
nil];

Directory Loading Time

One of the features of my application is to allow users to save images. These images are later presented in a detail view of a UITableView and in the cells of the UITableView. However, when returning to the page that is displaying the cells it takes a noticeably long time for it to load. I believe this is because the images are saved to the documents directory and every time the page loads they are reloaded from the directory. Should I be storing loading the images into an memory every time the application launches or am I way off in my theory. I have also tried compressing the images with the following code and it did not increase performance.
[[GTImageStore sharedStore] setImage:currentImage forKey:currentImageKey];
NSString *jpgName = [[NSString alloc] initWithFormat:#"Documents/%#.jpg", currentImageKey];
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:jpgName];
float scale;
if (currentImage.size.width < currentImage.size.height)
{
scale = 100/currentImage.size.width;
}
else if (currentImage.size.width > currentImage.size.height)
{
scale = 100/currentImage.size.height;
}
else
{
scale = 100/currentImage.size.width;
}
UIImage *image = [[UIImage alloc] initWithCGImage:currentImage.CGImage scale:scale orientation:[currentImage imageOrientation]];
[UIImageJPEGRepresentation(image, 0.5) writeToFile:jpgPath atomically:YES];
Any help is really appreciated! Thank you!
Code for adding cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UINib *giftCell = [UINib nibWithNibName:#"GiftCell" bundle:nil];
[tableView registerNib:giftCell forCellReuseIdentifier:#"UIGiftsTableCell"];
cell = [tableView dequeueReusableCellWithIdentifier:#"UIGiftsTableCell"];
if (!cell) {
cell = [[GTGiftCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"UIGiftsTableCell"];
}
// Determine gift at index path
GTGift *gift = (GTGift *)[[[GTGiftStore sharedStore] allGifts] objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[gift name]];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterLongStyle];
NSString *subText = [[NSString alloc] initWithFormat:#"Purchased on %#", [formatter stringFromDate:[gift datePurchased]]];
[[cell subTextLabel] setText:subText];
[[cell detailTopTextLabel] setText:[[gift givingTo] name]];
[[cell detailMiddleTextLabel] setText:[[gift reasonFor] name]];
[[cell detailBottomTextLabel] setText:[[gift boughtFrom] name]];
NSString *jpgName = [[NSString alloc] initWithFormat:#"Documents/%#.jpg", [gift imageKey]];
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:jpgName];
UIImage *imageToLoad = [[UIImage alloc] initWithContentsOfFile:jpgPath];
[[[cell image] layer] setBorderColor:[[UIColor lightGrayColor] CGColor]];
[[[cell image] layer] setBorderWidth:1];
[[cell image] setClipsToBounds:YES];
[[cell image] setContentMode:UIViewContentModeScaleAspectFill];
[[cell image] setImage:imageToLoad];
return cell;
}
I have created a custom cell using a xib file with a viewController named GTGiftCell.
There are two approaches you can take
If your application needs to load the images as they change then you keep with loading the images as you are , but you should read apples Concurrency Programming Guide to improve performance if the images need to update and change w/o the user refreshing the view
Load your images when the application loads but once again to improve performance read the Concurrency Programming Guide

Animate Spinner when loading new page

I have a UITableView which from an external RSS feed.
When you select a row it uses navigationController and slides in from the right, the problem is that the RSS feed contains images therefore it can can take a few seconds to load and without any indication of what is going on you can mistake it for an application crash.
I decided to add a spinner so that you know that new page is loading.
Here is my code:
RootViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Loading New Page");
[tableView deselectRowAtIndexPath:indexPath animated:YES];
DetailsViewController *detailViewController = [[DetailsViewController alloc] initWithNibName:#"DetailsViewController" bundle:nil];
detailViewController.item = [rssItems objectAtIndex:floor(indexPath.row/2)];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinner.center = CGPointMake(160, 240);
[self.view addSubview:spinner];
[spinner startAnimating];
[spinner release];
}
DetailsViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
NSString *imgURL = [item objectForKey:#"image"];
NSData *mydata = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imgURL]];
item_photo.image = [[UIImage alloc] initWithData:mydata];
item_title.text = [item objectForKey:#"title"];
item_date.text = [NSString stringWithFormat:#"Date: %#",[item objectForKey:#"date"]];
item_time.text = [NSString stringWithFormat:#"Time: %#",[item objectForKey:#"time"]];
item_cost.text = [NSString stringWithFormat:#"Cost: £%#",[item objectForKey:#"cost"]];
item_info.text = [item objectForKey:#"description"];
self.navigationItem.title = #"Event Type";
}
There are two problems with this code.
The Spinner does not active until after the new page has loaded.
The Spinner does not disable once loaded.
If anyone could help me with this problem i would be truly gratefully.
You are adding the activity indicator view to the view of the controller which is pushing the detail view controller, so you wont see it anyway
try moving the second group of code to the viewDidLoad method of DetailsViewController, you can call stopAnimating on the activity indicator when you are finished loading. To get a reference to the UIActivityIndicator you should add a tag
e.g. in viewDidLoad
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinner.center = CGPointMake(160, 240);
spinner.tag = 12;
[self.view addSubview:spinner];
[spinner startAnimating];
[spinner release];
in the loadingFinished method (whichever method is called when finished loading)
[[self.view viewWithTag:12] stopAnimating];
You need to do some work in a background thread. If the following line is the one that takes the time:
detailViewController.item = [rssItems objectAtIndex:floor(indexPath.row/2)];
Then you could do this in the background with GCD:
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// This is the operation that blocks the main thread, so we execute it in a background thread
id item = [rssItems objectAtIndex:floor(indexPath.row/2)];
// UIKit calls need to be made on the main thread, so re-dispatch there
dispatch_async(dispatch_get_main_queue(), ^{
detailViewController.item = item;
[spinner stopAnimating];
});
});
And +1 to #wattson12 - you need to add the spinner to the new view instead. Alternatively you could add the spinner to the current view, and instead put the pushViewControllercall into your GCD main-queue block.
Final point - you'll want to remove the spinner from its superview once you stop it animating. Alternatively, you can have a single instance of the spinner, and set hidesWhenStopped to YES.
This is a spinning wheel over a blurred view in swift:
func blurScence(){
let blurEffect: UIBlurEffect = UIBlurEffect(style: .Dark)
let blurView: UIVisualEffectView = UIVisualEffectView(effect: blurEffect)
blurView.translatesAutoresizingMaskIntoConstraints = false
blurView.frame = self.view.frame
let spinner = UIActivityIndicatorView(activityIndicatorStyle:.White)
spinner.center=blurView.center
blurView.addSubview(spinner)
spinner.startAnimating()
self.view.addSubview(blurView)
}

iphone mkannotation: warning on left callout after map has loaded

I have a MKMapview loading with maybe 5 annotations (right now). It loads fine, with the annotations as well. Each annotation contains the correct left and right callout. However after a while (maybe 2 minutes) i often get a EXC_BAD_ACCESS crash, on the left callout of an annotation...
- (MKAnnotationView *) mapView:(MKMapView *)thisMapView
viewForAnnotation:(MapAnnotations *)annotation
{
static NSString *MapIdentifier = #"MapIdentifier";
UIImageView *myImageView;
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[thisMapView dequeueReusableAnnotationViewWithIdentifier:MapIdentifier];
if(annotationView == nil)
{
NSString * id = [NSString stringWithFormat:#"%d", (annotation).tag];
NSString * postPhoto = [NSString stringWithFormat:#"id=%#",id];
NSString * hostStrPhoto = #"http://domain.com/get_image.php?";
hostStrPhoto = [hostStrPhoto stringByAppendingString:postPhoto];
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:hostStrPhoto]];
myImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData: imgData]];
myImageView.frame = CGRectMake(0,0,31,31);
annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MapIdentifier] autorelease];
}
annotationView.animatesDrop=TRUE;
annotationView.canShowCallout = YES;
annotationView.leftCalloutAccessoryView = myImageView; //<--where I am getting the error, after all the annotations have loaded.
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
[myImageView autorelease];
}
I am thinking maybe my app is still trying to load annotations, but I can't figure out why. As well i am getting some memory warnings when the map is loaded, so perhaps I am not releasing some objects the way i should be, i'm still kind of new to how the memory management works, so any suggestions would be helpful.
If you end up re-using an annotation view, myImageView isn't created, yet you're releasing it. Set myImageView to nil at the top.
- (MKAnnotationView *) mapView:(MKMapView *)thisMapView viewForAnnotation:(MapAnnotations *)annotation {
static NSString *MapIdentifier = #"MapIdentifier";
UIImageView *myImageView = nil;
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[thisMapView dequeueReusableAnnotationViewWithIdentifier:MapIdentifier];
if(annotationView == nil) {
NSString * id = [NSString stringWithFormat:#"%d", (annotation).tag];
NSString * postPhoto = [NSString stringWithFormat:#"id=%#",id];
NSString * hostStrPhoto = #"http://domain.com/get_image.php?";
hostStrPhoto = [hostStrPhoto stringByAppendingString:postPhoto];
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:hostStrPhoto]];
myImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData: imgData]];
myImageView.frame = CGRectMake(0,0,31,31);
annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MapIdentifier] autorelease];
}
annotationView.animatesDrop=TRUE;
annotationView.canShowCallout = YES;
annotationView.leftCalloutAccessoryView = myImageView; //<--where I am getting the error, after all the annotations have loaded.
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return annotationView;
[myImageView release];
}