My idea is to have several (maybe as much as 100) pinpoints in a Google map.
I have created a button in the annotation message that appears when I click the pin. I want each pinpoint to be connected to a website. A different website for each pinpoint.
But at the moment I use this:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
[[UIApplication sharedApplication]
openURL:[NSURL URLWithString: #"http://www.google.co.uk"]];
The problem is that with this code, all the pinpoints open the same website.
Is there any way I can specify a web address for each pinpoint?
#import "ViewController.h"
#import "NewClass.h"
#implementation ViewController
#synthesize mapview;
NSString *myString;
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
//[[UIApplication sharedApplication]
//openURL:[NSURL URLWithString: #"http://www.arebikepark.se"]];
NewClass *ann = (NewClass *)view.annotation;
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:ann.website]];
}
-(IBAction)getLocation {
mapview.showsUserLocation = YES;
}
-(IBAction)setMap:(id)sender {
switch (((UISegmentedControl *) sender).selectedSegmentIndex) {
case 0:
mapview.mapType = MKMapTypeStandard;
break;
case 1:
mapview.mapType = MKMapTypeSatellite;
break;
case 2:
mapview.mapType = MKMapTypeHybrid;
break;
default:
break;
}
}
- (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 = 63.399785761795506;
region.center.longitude = 12.91691780090332;
region.span.longitudeDelta = 100.0f;
region.span.latitudeDelta = 100.0f;
[mapview setRegion:region animated:YES];
NewClass *ann = [[NewClass alloc] init];
ann.title = #"Åre";
ann.subtitle = #"www.arebikepark.se";
ann.coordinate = region.center;
ann.website = #"arebikepark.se";
[mapview addAnnotation:ann];
MKCoordinateRegion region1 = { {0.0, 0.0 }, {0.0, 0.0 } };
region1.center.latitude = 61.717050948488904;
region1.center.longitude = 16.153764724731445;
region1.span.longitudeDelta = 100.0f;
region1.span.latitudeDelta = 100.0f;
[mapview setRegion:region1 animated:YES];
NewClass *ann1 = [[NewClass alloc] init];
ann1.title = #"Järvsö";
ann1.subtitle = #"www.jarvsobergscykelpark.se";
ann1.coordinate = region1.center;
ann.website = #"www.jarvsobergscykelpark.se";
[mapview addAnnotation:ann1];
MKCoordinateRegion region2 = { {0.0, 0.0 }, {0.0, 0.0 } };
region2.center.latitude = 57.84191869696362;
region2.center.longitude = 12.02951431274414;
region2.span.longitudeDelta = 100.0f;
region2.span.latitudeDelta = 100.0f;
[mapview setRegion:region2 animated:YES];
NewClass *ann2 = [[NewClass alloc] init];
ann2.title = #"Ale";
ann2.subtitle = #"www.alebikepark.se";
ann2.coordinate = region2.center;
[mapview addAnnotation:ann2];
MKCoordinateRegion region3 = { {0.0, 0.0 }, {0.0, 0.0 } };
region3.center.latitude = 61.17768100166834;
region3.center.longitude = 13.261871337890625;
region3.span.longitudeDelta = 100.0f;
region3.span.latitudeDelta = 100.0f;
[mapview setRegion:region3 animated:YES];
NewClass *ann3 = [[NewClass alloc] init];
ann3.title = #"Kläppen";
ann3.subtitle = #"www.klappen.se/sv/Sommar/Bikepark";
ann3.coordinate = region3.center;
ann3.website = #"www.klappen.se/sv/Sommar/Bikepark";
[mapview addAnnotation:ann3];
MKCoordinateRegion region4 = { {0.0, 0.0 }, {0.0, 0.0 } };
region4.center.latitude = 65.82881853569008;
region4.center.longitude = 15.067813396453857;
region4.span.longitudeDelta = 100.0f;
region4.span.latitudeDelta = 100.0f;
[mapview setRegion:region4 animated:YES];
NewClass *ann4 = [[NewClass alloc] init];
ann4.title = #"Hemavan";
ann4.subtitle = #"www.bikepark.nu";
ann4.coordinate = region4.center;
ann4.website = #"www.bikepark.nu";
[mapview addAnnotation:ann4];
MKCoordinateRegion region5 = { {0.0, 0.0 }, {0.0, 0.0 } };
region5.center.latitude = 63.29058608431198;
region5.center.longitude = 18.7042236328125;
region5.span.longitudeDelta = 100.0f;
region5.span.latitudeDelta = 100.0f;
[mapview setRegion:region5 animated:YES];
NewClass *ann5 = [[NewClass alloc] init];
ann5.title = #"Örnsköldsvik";
ann5.subtitle = #"www.hkbikepark.se";
ann5.coordinate = region5.center;
ann5.website = #"www.hkbikepark.se";
[mapview addAnnotation:ann5];
}
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *MyPin =(MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"MyPin"];
if (!MyPin) {
MyPin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"MyPin"];
MyPin.pinColor = MKPinAnnotationColorRed;
MyPin.canShowCallout = YES;
UIButton *details = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
MyPin.rightCalloutAccessoryView = details;
MyPin.canShowCallout = YES;
}
return MyPin;
}
#end
Add a property to your custom annotation class (the one that implements MKAnnotation) that stores the annotation's website. Set this property when you add the annotation to the map:
ann.website = #"http://www.google.co.uk";
[mapView addAnnotation:ann];
Then in the calloutAccessoryControlTapped delegate method, you can access this property:
MyAnnotationClass *ann = (MyAnnotationClass *)view.annotation;
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:ann.website]];
Based on the additional code you posted, the problem is that the website url strings don't have the http:// scheme prefix which the URLWithString method needs to convert the string to a URL. Because the url strings are invalid, the method returns nil which results in the openURL method doing nothing.
So, for example, the lines that set the website property should be:
ann.website = #"http://www.arebikepark.se";
ann1.website = #"http://www.jarvsobergscykelpark.se";
ann2.website = #"http://www.alebikepark.se"; //(line was missing completely)
ann3.website = #"http://www.klappen.se/sv/Sommar/Bikepark";
ann4.website = #"http://www.bikepark.nu";
ann5.website = #"http://www.hkbikepark.se";
Additionally, though the above urls are not a problem, if you intend to use urls with query strings that might contain special characters, you'll also need to escape the url string before passing it. One way is to use the stringByAddingPercentEscapesUsingEncoding method. See this answer by Dave DeLong for an example and some precautions/limitations/alternatives with that method.
Finally, unrelated to your main issue but, here are some additional comments on the code:
You don't need to create a region for each annotation just to set its coordinate. You can just do ann.coordinate = CLLocationCoordinate2DMake(63.399785761795506, 12.91691780090332);
If you are not using ARC, there are several memory leaks.
In viewForAnnotation, you should add an else part to the if statement: else MyPin.annotation = annotation; in case an annotation view is re-used for a different annotation. It probably won't happen with so few annotations but it's logically and technically required.
If you want the user location to appear as a blue dot instead of a red pin, you'll need to add this to the top of the viewForAnnotation method: if ([annotation isKindOfClass:[MKUserLocation class]]) return nil;
Related
I have this code that I need altered slightly. The code I have below creates a pin on my current location (perfectly as I might add).
The only problem is that I need the code only to be run when I click a button, not every time I move.
Here is the code of the current location and the pin.
- (void)viewDidLoad {
[super viewDidLoad];
[self.mapView setDelegate:self];
[self.mapView setShowsUserLocation:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
// zoom to region containing the user location
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 700, 700);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
// add the annotation
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"Your Car";
//point.subtitle = #"";
[self.mapView addAnnotation:point];
}
I need this to run when I click a button such as:
-(IBAction)addPin
{
}
In the viewDidLoad: method,
Create a button like this:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(showPinOnClick)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(100.0, 200.0, 150.0, 60.0);
[self.view addSubview:button];
// create the method defined as selector method for the UIButton in your viewcontroller
-(void) showPinOnClick{
//paste your code here to show the pin
CLLocationCoordinate2D location = self.mapview.userLocation.coordinate;
MKCoordinateRegion region;
MKCoordinateSpan span;
location.latitude = -32.008081;
location.longitude = 115.757671;
span.latitudeDelta = 0.03;
span.longitudeDelta = 0.03;
region.span = span;
region.center = location;
[_mapview setRegion:region animated:YES];
[_mapview regionThatFits:region];
//Create your annotation
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
// Set your annotation to point at your coordinate
point.coordinate = location;
point.title = #"Your Car";
//Drop pin on map
[_mapview addAnnotation:point];
[_mapview selectAnnotation:point animated:NO];
}
I have a problem with my mapview. When I go to the view it works but when I go to another view and go back to the mapview it doesn't work anymore. I get the right latitude and longitude when I NSLog() it, so that is not the problem.
Code:
- (void) viewDidAppear:(BOOL)animated {
if(IS_IPHONE5) {
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,300,320,300)];
} else {
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,250,320,250)];
}
mapView.mapType = MKMapTypeStandard;
CLLocationCoordinate2D coord = {.latitude = [testLatitude floatValue], .longitude = [testLongitude floatValue]};
MKCoordinateSpan span = {.latitudeDelta = 0.05, .longitudeDelta = 0.05};
MKCoordinateRegion region = {coord, span};
[mapView setRegion:region];
[self.view addSubview:mapView];
CLLocationCoordinate2D annotationCoord;
annotationCoord.latitude = [testLatitude floatValue];
annotationCoord.longitude = [testLongitude floatValue];
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = annotationCoord;
annotationPoint.title = stringTitle;
[mapView addAnnotation:annotationPoint];
}
based on what you've shown you keep adding map views (a new one each time the VC appears)
you seem to have forgotten to remove it!?
why are you allocating your mapview in viewdidAppear? it will add you map view multiple times on the screen if it is not removed on viewdidDisAppear
In your case you are not removing the map view that is already added , what you can do is use
- (void)viewWillAppear Method to Remove the map like that
- (void)viewWillAppear:(BOOL)animated
{
if(map != nil)
{
[map removeFromSuperview];
}
}
it will removed the previous map view before adding the new map
Add this code to your view:
-(void)viewDidDisappear:(BOOL)animated {
if(mapView)
{
[mapView removeFromSuperview];
}
}
}
Also to remove all subviews:
-(void)viewWillAppear:(BOOL)animated {
for (UIView *view in self.subviews) {
[view removeFromSuperview];
}
}
Try like this it may help
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:(BOOL)animated];
if(IS_IPHONE5) {
if (mapView == nil){
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,300,320,300)];
[mapview setDelegate:self];
}
} else {
if (mapView == nil){
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,250,320,250)];
[mapview setDelegate:self];
}
}
//Add ramaining Code
}
viewDidDisappear Code
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:(BOOL)animated];
[mapView removeFromSuperview];
mapView = nil;
}
ViewDidAppear: if mapview nil we are creating the mapview otherwise not
viewDidDisappear:if we go outside view we are removing the map
I started programming recently, and I have a question! I have created a mapview with the annotation and disclosure button.
How can I create multiple annotations with disclosure button that, after a tap, go to different descriptions based on the annotation choice?
This is my code:
#synthesize mapView;
-(void)viewDidLoad {
[super viewDidLoad];
[mapView setMapType:MKMapTypeHybrid];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
[mapView setDelegate:self];
MKCoordinateRegion bigBen = { {0.0, 0.0} , {0.0, 0.0} };
bigBen.center.latitude = 51.50063;
bigBen.center.longitude = -0.124629;
bigBen.span.longitudeDelta = 0.02f;
bigBen.span.latitudeDelta = 0.02f;
[mapView setRegion:bigBen animated:YES];
Annotation *ann1 = [[Annotation alloc] init];
ann1.title = #"Big Ben";
ann1.subtitle = #"Your subtitle";
ann1.coordinate = bigBen.center;
[mapView addAnnotation: ann1];
MKCoordinateRegion Bridge = { {0.0, 0.0} , {0.0, 0.0} };
Bridge.center.latitude = 51.500809;
Bridge.center.longitude = -0.120914;
Bridge.span.longitudeDelta = 0.02f;
Bridge.span.latitudeDelta = 0.02f;
[mapView setRegion:Bridge animated:YES];
Annotation *ann2 = [[Annotation alloc] init];
ann2.title = #"Westminster Bridge";
ann2.subtitle = #"Your subtitle";
ann2.coordinate = Bridge.center;
[mapView addAnnotation:ann2];
}
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKPinAnnotationView *MyPin=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
MyPin.pinColor = MKPinAnnotationColorPurple;
UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[advertButton addTarget:self action:#selector(button:) forControlEvents:UIControlEventTouchUpInside];
MyPin.rightCalloutAccessoryView = advertButton;
MyPin.draggable = NO;
MyPin.highlighted = YES;
MyPin.animatesDrop=TRUE;
MyPin.canShowCallout = YES;
return MyPin;
}
The usual way to do it is to implement -mapView:annotationView:calloutAccessoryControlTapped: in your map view delegate. You can use the annotaionView parameter to decide which annotaion was tapped and what information you want to display.
I'm struggling with setting the subtitle of an annotation in MapView, once it has been clicked.
.m:
MKCoordinateRegion England = { {0.0, 0.0} , {0.0, 0.0} };
England.center.latitude = 51.50063;
England.center.longitude = -0.124629;
England.span.longitudeDelta = 100.0f;
England.span.latitudeDelta = 100.0f;
[mapView setRegion:England animated:YES];
Annotation *ann1 = [[Annotation alloc] init];
ann1.title = #"England";
ann1.subtitle = #"subtitle";
ann1.coordinate = England.center;
[mapView addAnnotation:ann1];
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation: (id<MKAnnotation>)annotation {
MKPinAnnotationView *MyPin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"]; MyPin.pinColor = MKPinAnnotationColorPurple;
UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[advertButton addTarget:self action:#selector(button:) forControlEvents:UIControlEventTouchUpInside];
MyPin.rightCalloutAccessoryView = advertButton;
MyPin.draggable = NO;
MyPin.highlighted = YES;
MyPin.animatesDrop = TRUE;
MyPin.canShowCallout = YES;
return MyPin;
}
- (void)mapView:(MKMapView *)mapView1 didSelectAnnotationView:(MKAnnotationView *)view
{
id<MKAnnotation> selectedAnn = [mapView.selectedAnnotations objectAtIndex:0];
country_title = selectedAnn.title;
selectedAnn.subtitle = #"NEW SUBTITLE";
}
How do I set the subtitle once the annotation has been clicked? I wan't to do it that way, because I get some rows from mysql when it's clicked.. but I don't know how to update the subtitle for the specific annotation?
Thanks in advance! :)
id<MKAnnotation> selectedAnn = view.annotation;
[mapview removeAnnotation:selectedAnn];
.. Add Annotation with new subtitle
[mapview addAnnotation:newselectedAnn];
[newselectedAnn setSelected:Yes animated:No];
Hope this helps
I created a simple application with the MapKit framework. When it starts, the user location is zoomed in and shown. But when I zoom out and scroll around the map, it automatically centralizes it self to the user location again after a couple of seconds. How can I stop this?
In the m-file:
#import "APPNAMEViewController.h"
#import <MapKit/MapKit.h>
#synthesize mapview;
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)aUserLocation {
mapView.scrollEnabled = YES;
mapView.zoomEnabled = YES;
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.005;
span.longitudeDelta = 0.005;
CLLocationCoordinate2D location;
location.latitude = aUserLocation.coordinate.latitude;
location.longitude = aUserLocation.coordinate.longitude;
region.span = span;
region.center = location;
[mapView setRegion:region animated:NO];
[mapView setUserTrackingMode:MKUserTrackingModeNone animated:NO];
}
- (void)viewDidLoad
{
[super viewDidLoad];
mapview = [[MKMapView alloc]
initWithFrame:CGRectMake(0,
44,
self.mapview.bounds.size.width,
self.mapview.bounds.size.height)
];
mapview.showsUserLocation = YES;
mapview.mapType = MKMapTypeStandard;
mapview.delegate = self;
[mapview setUserTrackingMode:MKUserTrackingModeNone animated:NO];
[self.view addSubview:mapview];
}
Please help me :)
Best regards
Michal
Remove [mapView setRegion:region animated:NO]; in - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)aUserLocation
[mapView setRegion:region animated:NO]; //Changes the currently visible region and optionally animates the change.
Remove : [mapView setUserTrackingMode:MKUserTrackingModeNone animated:NO];
This makes the map center on current location.