I am writing an application that displays a thumbnail from a server in the leftCalloutAccessoryView. Before I actually get the image, I display a placemark image. Once the photo is downloaded, a method is called and I want to update that image without removing the original annotation and placing another. I just wan the image to switch from the placeholder to the downloaded thumbnail. Below is the code that does not work, but if someone could let me know if I'm on the right track, that would be great.
MyAnnotationClass *annotation=[[MyAnnotationClass alloc] initWithCoordinate:item.location];
[annotation setItem:item];
if(item.title){
annotation.name=item.title;
}
else{
annotation.name=#"no title";
}
[annotation setDescription:[[NSString alloc] initWithFormat:#"Views:%d Likes:%d Comments:%d",item.views,item.likes,item.comments]];
[annotation setImage:[[photo.thumb copyWithDimensions: CGSizeMake(32.0, 32.0)] autorelease]];
MKAnnotationView *av=[__mapView viewForAnnotation:annotation];
UIImageView *imageView=[[UIImageView alloc] initWithImage:annotation.image];
imageView.frame=CGRectMake(0.0, 0.0, 32.0, 32.0);
av.leftCalloutAccessoryView=imageView;
[annotation release];
I have been looking around here for quite sometime, but nothing that I can find will do what I need. Thanks
If the annotation is already on the map and you want to update it, don't create a new one.
Instead, find the annotation you want to update in the map view's annotations array and update its properties. Then call viewForAnnotation: on that existing annotation and update the leftCalloutAccessoryView.
Also, make sure the viewForAnnotation delegate method has logic that sets the leftCalloutAccessoryView to either the placeholder image or the actual image by checking the annotation's properties (and not always the placeholder image).
This other question has some sample code that may help.
Related
In my application I have a MKMapView where several annotations are shown. The map rotates based on the heading of the device. To rotate the map the following statement is performed (called by the method locationManager: didUpdateHeading:)
self.navigationMapView.mapView.transform = CGAffineTransformMakeRotation(-heading);
where the heading (magnetic) is expressed in radians. What I noticed it's that even the annotations in the map rotate and I don't want it. I tried to fix it in the following method:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
static NSString *identifier = #"AnnotationViewIdentifier";
MKAnnotationView *av = [mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (av == nil) {
av = [[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:identifier] autorelease];
}
else{
av.annotation = annotation;
}
av.transform = CGAffineTransformMakeRotation(degreesToRadians(self.arController.currentHeading.magneticHeading));
av.canShowCallout = YES;
return av;
}
and I want to call this method from "didUpdateHeading:" but I really don't know how to do it. The TableView class has the reloadData function that calls the delegate method but here the things seem different. Any suggestions?!
Another question, my annotations on the map show the distance from the user, I would like to update them (distance label) as soon as the user change location. Any suggestions?!
So with a MKMapView having that be called properly is a little bit annoying. Essentially you have one of two options. Option 1: Create an array of the annotation on the screen and remove that from the map_view and then re-add them to the map_view. Essentially creating your own reload data function. Option 2: Do something simple such as
CGLocationCoordinate2D coordinate = map_view.center;
map_view.center = coordinate;
-- Essentially the point is to reset a property of the map causing it to redraw. However this option is not always going to work. Option 1 has a higher chance of working however that one can also fail, so if simply taking the annotations off and re-adding them causes nothing to happen then simply decreate the map and then recreate the map at the end of your map refresh function something like.
[my_map_view removeFromSuperView];
[my_map_view release];
my_map_view = nil;
my_map_view = [[MKMapView alloc] initWithFrame:CGRectMake(0,0,320,480)];
one of these options should work. I had to do option one for my solution however I know some people are lucky and option 2 works just as well.
I have a problem with my app where the code for which is far too long to go into, but suffice to say when i'm removing a UIView and replacing it with a new one like so:
NSLog(#" .. %#", (Icon *)[self viewWithTag:index]);
Icon *icon = (Icon *)[self viewWithTag:index];
CGRect frame = icon.frame;
int tag = icon.tag;
[icon removeFromSuperview];
[icon release];
Icon *icon2 = [[Icon alloc] init];
icon2.frame = frame;
[icon2 makeIconStandardWithTag:(int)tag];
[self addSubview:icon2];
It does some weird thing where that NSLog the first time (because the view is already there) shows that the object is an icon, but the second time after running this code shows that it's a UIImageView for some reason now, and it displays what i presume to be the original icon at some odd position on the screen. It's very erratic behaviour. But what i do know is this:
Removing the [icon removeFromSuperview]; line, although keeping the object there, stops this behaviour and causes the NSLog to return an Icon, as it should.
So my guess is that it's not removing icon correctly. Is there a way to completely remove icon, or is removeFromSuperview as far as i can go. What i could do is just have it set to alpha = 0 but this is more of a patch-over solution and not how i want to solve it.
"Is there a way to completely remove
icon, or is removeFromSuperview as far
as i can go"
You can set the object to nil:
icon = nil;
Can you verify what "self" is in this line of code:
It might not be what you think.
[self addSubview:icon2];
NSLog(#" Self is %#", self);
This is a guess, but try setting self.tag to -1 or some other value that doesn't collide with the tags you're setting on your Icon objects. The viewWithTag: method searches the current view and its subviews for a match, so if self.tag == 0 and you call [self viewWithTag:0], you'll get self.
Did you retain icon somewhere prior to this? If not, no need to release it after the call to removeFromSuperview. Similarly, unless you need the reference to icon2 elsewhere, you can release that after calling addSubview.
Views retain views added via addSubview, and they release views removed via removeFromSuperview.
Im trying to use the MKMap API and integrate a database table id so I can click a button detail disclosure to send the user to another page with further information. Ive been all over teh MKMapKit on the Apple site to find some property or method to help me with this and went over a few tutorials with no answers.
Ive tried to attach the id into the subtitle context so I can retrieve it in the MKAnnotationView where I make my MKPinAnnotationView and add teh button to the rightCalloutAccessoryView. It errors out and doesnt want to work.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
MKPinAnnotationView *annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"mkpin"];
annView.animatesDrop = YES;
annView.canShowCallout = YES;
UIButton *disclosureButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annView.rightCalloutAccessoryView = disclosureButton;
return annView;
}
I used this technique for an individual pin on a map and it seemed to work but I didnt require an id...
When I try to get the subtitle of the annotation it kills the app. I know the (id)annotation is an integer but I dont know how to manipulate this information. This function above I think is called after my code:
[mapView addAnnotations:markers]; //where markers is an array of title, subtitle aka id
Any help would be greatly appreciated.
The subtitle property is for a subtitle, not a database id. No good can come from abusing it in that way. Even if you could get it to work, it's a horrible approach.
All you have to do is give your annotation class an appropriate property to store your id. When you are passed the annotation, you can access it from there by casting to your annotation class. When you are passed the annotation view in other delegate methods, you can access the annotation through its annotation property.
I am implementing a MKMapView based application. In that I am using a custom image instead of displaying a pin by using MKAnnotationView.Image property. It is not working. It keeps showing the standard pin in red but not the image I am pointing too. Any ideas?
- (void)setPin:(MKPinAnnotationView *)aPin forAnnotation:(id <MKAnnotation>)anAnnotation {
if (anAnnotation == self.userAnnotation) {
aPin.image = [UIImage imageNamed:#"youarehere.png"];
aPin.opaque = NO;
aPin.pinColor = MKPinAnnotationColorRed;
}
}
If you use MKPinAnnotationView like you are then you don't get to set the image only the pinColor. MKPinAnnotationView only has pinColor and animatesDrop as the properties.
You want to use the parent class MKAnnotationView. It will let you set the image.
Read the Class Reference for each and it will make sense. This is one of the times that Objective-C makes me crazy because when you are reading those long class names in the docs, it's easy to scan right over the "Pin" variation in the class name.
I have a UISegmentedControl and I have some photos, my initial aim is when ever I click on a particular segment one particular image should appear on the view.
For example: If i have four segments and four images then upon each segment I click I must see a image.
Here I have taken an NSArray and Uploaded all these images using this particular below code:
NSArray * images = [NSArray arrayWithObjects:[UIImage imageNamed:#"f.ppg"], [UIImage imageNamed:#"t.ppg"....etc ], nil];
and after this I want to attach each particular image to a segment index. So here is the code which I wrote.
-(IBAction) segmentActionChanged:(id)sender
{
int segment = mSegment.selectedSegmentIndex;
mImageView.image=[images objectAtIndex:segment];
}
While compiling the application I am not getting any Images displayed and it is quiting abruptly.
Any help regarding this.
To Answer questions 1 and 3 (I think).
to display an image, you will need a UIImageView somewhere. a simple way to do this would be to create an method such as this.
//somewhere in viewDidLoad perhaps?
//title array is an array of strings to use as the label on each section of your control
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:titleArray];
//this sets the segmentAction: method as the selector for your particular UISegmentedControl
//(so when its value is changed, segmentAction: gets called)
[segmentedControl addTarget:self action:#selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
//the segmentAction: method
- (IBAction) segmentAction:(id)sender
{
//This assumes you have declared the imageView elsewhere, as well as the array and that you
//are using Interface Builder to create/hookup the segmentControl. Basically
myImageView.image = [myImageArray objectAtIndex:sender.selectedSegmentIndex];
}
A few Notes: this does not take advantage of lazy loading, since you are creating and holding all of your images in an array prior to showing them. I would suggest creating an instance variable for the UISegmentedControl so you can access it anywhere also.
Disclaimer: this code is not complete and assumes some initializations.
To answer question number two:A UIImagePickerController is used when dealing with the phone's/devices camera or saved photos album. It is covered in the documentation.
Looks like you're missing a retain.