Create overlay from user interaction on MKMapView? - iphone

I have two questions,
How to create an overlay on a MKMapkitView from user's touch down events? i.e. To keep it simple, the user touches down and it creates a MKCircle overlay
How does the Maps application implements the "dropped pin" on touch down? Anybody knows or have some code examples on how to accomplish something similar?
Any pointers would be greatly appreciated. I've been googling and reading lots of docs without much success as you can see.

Below is an example that creates a circle and drops a pin where the user touches and holds their finger for 1 second. It uses a UILongPressGestureRecognizer which is added to the mapView wherever the map is initialized (eg. viewDidLoad).
Make sure the mapView's delegate is set also.
// In viewDidLoad or where map is initialized...
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
lpgr.minimumPressDuration = 1.0; //user must hold for 1 second
[mapView addGestureRecognizer:lpgr];
[lpgr release];
...
- (void)handleLongPress:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateBegan)
return;
CGPoint touchPoint = [gestureRecognizer locationInView:mapView];
CLLocationCoordinate2D touchMapCoordinate = [mapView convertPoint:touchPoint toCoordinateFromView:mapView];
//add pin where user touched down...
MKPointAnnotation *pa = [[MKPointAnnotation alloc] init];
pa.coordinate = touchMapCoordinate;
pa.title = #"Hello";
[mapView addAnnotation:pa];
[pa release];
//add circle with 5km radius where user touched down...
MKCircle *circle = [MKCircle circleWithCenterCoordinate:touchMapCoordinate radius:5000];
[mapView addOverlay:circle];
}
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay
{
MKCircleView* circleView = [[[MKCircleView alloc] initWithOverlay:overlay] autorelease];
circleView.fillColor = [UIColor redColor];
return circleView;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *AnnotationIdentifier = #"Annotation";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop = YES;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}

Related

Logic Issue - MapKit

Following is my MapKitDisplayViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = 22.569722 ;
region.center.longitude = 88.369722;
[mapView setRegion:region animated:YES];
[mapView setDelegate:self];
DisplayMap *ann = [[DisplayMap alloc] init];
ann.title = [person name];
ann.subtitle = [person address];
ann.person = person;
ann.coordinate = region.center;
[mapView addAnnotation:ann];
}
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:
(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
UIImageView *iconView = [[UIImageView alloc] initWithImage: [UIImage imageWithString:#?????????????????];
annotationView.leftCalloutAccessoryView = iconView;
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
}
return pinView;
}
You will see the line where it'll say ???????? I need to display an image there.
When the user clicks a pin point, then the popup will appear. Title, subtitle and the image is suppose to be displayed on the popup. I believe that the following line should display the image for that popup. But i am unable to pass the Person object's (or the pipoint which contains the person object) image URL to this method. Can you help me display the selected Image URL here.
It doesn't fail. I need to know how to pass the person object
selected by the user to viewForAnnotation method
Ahhh, I see know. I had a similar issue, and it can be a be tricky. I'm right in the middle of reworking my Annotation code, so you can see it since it doesn't work, but I you need to store something away that you can then later retrieve.
I made an object, MKAnnotation.
#interface FotoMapLocation : NSObject <MKAnnotation> {
So when I make an annotation, I create a FotoMapLocation object.
FotoMapLocation *annotation = [[FotoMapLocation alloc] initWithTitle:title
subtitle:subtitle
foto:aFoto
thumbnailImage:aFoto.thumbnailImage
];
[mapView addAnnotation:annotation];
Now, you can store anything here. So store your Person object in your subclass.
I know this is only halfway there, and very rambling. But I was right in the middle of ripping that code out, and then another fire came up, so it is currently in an in-between state. But I expect to return to it in a few days. I'll check back and if you don't have anything I'll update this answer.
This is what i did, in the viewForAnnotation method
DisplayMap *dm= (DisplayMap *)annotation;
NSString *url = [dm.person urlOfPerson];

Custom callOut for A pin in a mkMapview of iphone!! .... Data miss match for default call out and custom call out

I am trying for a custom callout for a pin dropped in a mapView .. I am able to do this by hiding the default callout of pinView and showing my custom call out there. ().. everything is working fine ... But only prob is i am not able to assign the correct information for the call out ..I had shown the Default call out in which info is different than my custom call out. I ve attached the scrren shot .....
Here is my code
-(void)mapViewImplementaion
{
[mapview setMapType:MKMapTypeStandard];
mapview.showsUserLocation=YES;
for (int i =0;i<[allResultsArr count];i++)
{
List_Map_details *object=[allResultsArr objectAtIndex:i];
CLLocationCoordinate2D coordinat = {[object.lati floatValue], [object.longi floatValue]};
[mapview setRegion:MKCoordinateRegionMake(coordinat,
MKCoordinateSpanMake(0.027f, 0.027f))];
DisplayMapPark *ann = [[DisplayMapPark alloc] init];
ann.title =[NSString stringWithFormat:#"%#",object.forRetailerName];
ann.subtitle=[NSString stringWithFormat:#"%# %# %#",object.forAddress,object.forZipCode,object.forCityName];
ann.latitude=[object.lati floatValue];
ann.longitude=[object.longi floatValue];
ann.coordinate = coordinat;
[mapview addAnnotation:ann];
[ann release];
}
CalloutMapAnnotationView *calloutMapAnnotationView;
int m=1;
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
MKAnnotationView *pinView = nil;
// here i wrote some code for my custom callout to generate(not shown)
if(annotation != mapview.userLocation)
{
//int i=0;
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapview dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
NSString *imagName = [NSString stringWithFormat:#"%d.png", m];
UIImage *image = [UIImage imageNamed:imagName];
[pinView setImage:image];
pinView.canShowCallout = NO;
// To show this in scrren Shot i set it to Yes;
[pinView setAnnotation:annotation];
pinView.tag=m;
UIButton *rightButton=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView=rightButton;
//pinView.rightCalloutAccessoryView.frame=CGRectMake(0, 0, 60, 60);
m++;
}
else
{
[mapview.userLocation setTitle:#"Ik ben hier"];
}
pinView.annotation = annotation;
[rightButton release];
return pinView;
}
Hi if any one is awre of this .. please help !!!!!
I solved this issue. It was the mistake by me. I was just not assigning the tags to the pins properly .. and when the user selects the pin i was reading some other pin's information.... Thanks all

detailButton unable to push information over. Pushed page always have empty labels

Hi can some1 plz help me....
The problem is this: Everything seems alright.. i am able to push to another page once i tap on the detailButton. However, the page which i am able to push to is always only a view without any values passed into the labels. All my labels in the view have nothing inside.. Am i doing something wrong or any wrong concept here?
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
BOOL isRed = NO;
//BOOL isPurple = YES;
if([annotation isKindOfClass:[MyAnnotation2 class]])
isRed = YES;
MKPinAnnotationView *pinView = nil;
if(isRed) {
static NSString *redPin = #"redPin";
pinView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:redPin];
if (!pinView) {
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:redPin] autorelease];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = detailButton;
}
else{
pinView.annotation = annotation;
}
}
else {
static NSString *greenPin = #"greenPin";
pinView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:greenPin];
if (!pinView) {
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:greenPin] autorelease];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = detailButton;
}
}
return pinView;
}
//
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"calloutAccessoryControlTapped");
if (self.patientDetailsViewController == nil) {
self.patientDetailsViewController = [[[PatientDetailsViewController alloc] initWithNibName:#"PatientDetailsViewController" bundle:nil] autorelease];
}
MyAnnotation2 *selectedObject = (MyAnnotation2 *)view.annotation;
_patientDetailsViewController.nric = selectedObject.title;
NSLog(#"%#",_patientDetailsViewController.nric);
[self.navigationController pushViewController:_patientDetailsViewController animated:YES];
}
Don't use your own target/action and tagging for the callout accessory button.
Instead, use the MKMapViewDelegate method calloutAccessoryControlTapped:. Remove the addTarget line and implement the delegate method.
In that delegate method, you can access the annotation tapped using:
MyAnnotation2 *selectedObject = (MyAnnotation2 *)view.annotation;

MKMapView not updating user position image

My MKMapView shows my position at startup but then the image never 'follows' me. The location gets updated and the screen does follow me, but the original "User Location" image stays behind.
Here is some code snippets:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(!pinView)
{
MKPinAnnotationView *customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
if(annotation == mapView.userLocation) customPinView.image = [self rotate:[UIImage imageNamed:#"myCar.png"] orientation:UIImageOrientationUp];
else customPinView.image = [UIImage imageNamed:#"randomPin.png"];
customPinView.animatesDrop = NO;
customPinView.canShowCallout = YES;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
-(void)locationUpdate:(CLLocation *)location
{
CLLocationCoordinate2D loc = [location coordinate];
if(isFollowing)
[myMapView setCenterCoordinate:loc];//Works
}
and in my viewDidLoad I do call: [myMapView setShowsUserLocation:YES]; which does work.
So basically somewhere I neglect updating my position or its most possibly where I draw the new image for my current position.
Can anyone possibly see what I am missing or doing wrong there for it to not follow my location updates?
Thanks.
It's not clear if this is the issue but the viewForAnnotation method doesn't look right.
The annotation image is only being set when an annotation view is created. If a view is re-used, the annotation property is updated but not the image. It's possible that the re-used view is for an annotation of a different type requiring a different image.
The method should look something like this:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
}
else
{
pinView.annotation = annotation;
}
if (annotation == mapView.userLocation)
pinView.image = [self rotate:[UIImage imageNamed:#"myCar.png"] orientation:UIImageOrientationUp];
else
pinView.image = [UIImage imageNamed:#"randomPin.png"];
return pinView;
}

MapKit doesn't show Blue Dot for Current Location

I am a newbie in MapKit for iPhone and tried to implement this, for some reason I can't see the current location blue dot, anyone else had this issue????
#import "DetailMapViewController.h"
#import "mapAnnotations.h"
#implementation DetailMapViewController
#synthesize inStock;
-(void)getlocation:(CLLocationCoordinate2D)loc
{
location = loc;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"Street View";
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.delegate=self;
//MKCoordinateRegion region;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(location, 5000, 5000);
mapAnnotations *ann = [[mapAnnotations alloc] init];
ann.title = #"";
ann.subtitle = #"";
ann.coordinate = region.center;
mapView.showsUserLocation = YES;
[mapView addAnnotation:ann];
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
[self.view insertSubview:mapView atIndex:0];
}
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
if (annotation == mapView.userLocation)
{
annView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"blueDot"];
if (annView != nil)
{
annView.annotation = annotation;
}
else
{
annView = [[[NSClassFromString(#"MKUserLocationView") alloc] initWithAnnotation:annotation reuseIdentifier:#"blueDot"] autorelease];
}
}
if([inStock isEqual:#"yes"]){
annView.pinColor = MKPinAnnotationColorGreen;
}
if([inStock isEqual:#"no"]){
annView.pinColor = MKPinAnnotationColorRed;
}
if([inStock isEqual:#"unknown"]){
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"greyPin.png"]];
[annView addSubview:imageView];
}
annView.animatesDrop=TRUE;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
return annView;
}
- (void)dealloc {
[super dealloc];
}
#end
The way the viewForAnnotation is currently written, it should actually crash when trying to show the current location because the "blue dot" annotation view doesn't have the pinColor or animatesDrop properties.
Try changing it to the following:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
if ([annotation isKindOfClass:MKUserLocation.class]) {
//user location view is being requested,
//return nil so it uses the default which is a blue dot...
return nil;
}
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
if([inStock isEqual:#"yes"]){
annView.pinColor = MKPinAnnotationColorGreen;
}
if([inStock isEqual:#"no"]){
annView.pinColor = MKPinAnnotationColorRed;
}
if([inStock isEqual:#"unknown"]){
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"greyPin.png"]];
[annView addSubview:imageView];
}
annView.animatesDrop=TRUE;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
return annView;
}
On the simulator, the user's location will be Cupertino, CA, USA (a little south of San Francisco). If your own annotation is not within 5000 meters of that, you won't see the blue dot. You'll have to zoom out to see it.
self.mapView.showsUserLocation = YES;