I am totally new to iOS development, and am creating a mapping application for a local river. The point of the application is to allow users to map out a route on the river by selecting different points. I am using MapKit to work on this, but have run into some issues. My main issue is how to add a button to an annotation so that once clicked, a detail window will open and the user can learn more about the point as well as add it to the trip. Here's my code, any thoughts will help!
#import "ViewController.h"
#import "CoreLocation/CLLocation.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// Add an annotation
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"Where am I?";
point.subtitle = #"I'm here!!!";
[self.mapView addAnnotation:point];
point.coordinate = CLLocationCoordinate2DMake(33.62258872997,-86.599988937378);
point.title = #"Civitan Park";
point.subtitle = #"Trussville, AL";
[self.mapView addAnnotation:point];
}
#end
Your map view delegate should implement –mapView:viewForAnnotation: and return an annotation view that has one of its accessory view properties set. The normal thing is to set the rightCalloutAccessoryView property to a UIButton whose type is UIButtonTypeDetailDisclosure. You map delegate should also implement -mapView:annotationView:calloutAccessoryControlTapped:, which will be called when the user taps the button in the accessory view. You can then push a detail view controller onto the navigation stack, or whatever else you like.
Related
I have an odd problem where I cannot get this method to do anything! I have added the map view delegate and delcaired the delegate in the top AND header file. I intend to just get a response when the user touches a bubble produced by tapping on a google maps marker
Here is what I have
#import "ViewController.h"
#import "Location.h"
#interface ViewController () <GMSMapViewDelegate>
#property(nonatomic)NSMutableArray* storedLocations;
#property(nonatomic)NSMutableArray* myPlaces;
#end
#implementation ViewController {
GMSMapView *mapView;
}
- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker{
UIAlertView* new = [[UIAlertView alloc] initWithTitle:#"Nice!" message:#"Good stuff" delegate:self cancelButtonTitle:#"Well Done!" otherButtonTitles:nil];
[new show];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Create Map View on scene with camera
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:0
longitude:0
zoom:0];
mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView.myLocationEnabled = YES;
self.view = mapView;
mapView.delegate = self;
As mentioned at the moment, touching the bubble does nothing
If you want to know if your marker is tapped, you should call the
(BOOL) mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *) marker method
The method you use, it will only been called if the info window of your marker is tapped.
Maybe you have to define a Title,
mapView.title = #"Test title";
then you can tap over the description window.
i am using google map api for display the location and search bar for search the location but when the GSMMarker display it snippet window hide inside the uisearchbar so any own please help me.
-(void) setupMarkerOnMap:(CLLocation *)loc PlaceName:(NSString *) strCityName
{
[[self getGoogleMap] clear];
[self getNextButton].enabled = YES;
placeMarker = [GMSMarker markerWithPosition:loc.coordinate];
placeMarker.map = [self getGoogleMap];
[placeMarker setTappable:NO];
placeMarker.snippet = strCityName;
placeMarker.icon = [UIImage imageNamed:#"LocationMarker.png"];
GMSCameraUpdate *updateCamera = [GMSCameraUpdate setTarget:placeMarker.position zoom:10.0];
[[self getGoogleMap] animateWithCameraUpdate:updateCamera];
[[self getGoogleMap] setSelectedMarker:placeMarker];
}
these my code snippet for marker add in google map and i attached image which can help you.
anyone can help me.
Thanks
First of all, Make sure that your Google map does not stack together with the search bar. Then you can use delegate to help you move the animate the marker's position inside the Google Map when you tap on any of the marker. Example code:-
Implement the Google Map Delegate
#interface YourViewController ()<GMSMapViewDelegate>
#property (weak, nonatomic) IBOutlet GMSMapView *mapView;
#end
Set the mapView Delegate to the current view controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
}
Whenever a marker is tapped, the
-(BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker{
[mapView animateToLocation:marker.position];
return YES;
}
If you have everything setup correctly and the map is big enough, info window should be displayed nicely inside the map.
I am trying to transfer a users location from a screen where I allow the user to take a picture to another view where I have a map. The purpose of this is to tag the image location on the map and have that be related with the image. The current code I have for launching the ability to take an image is as follows:
- (IBAction)takePhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion: NULL];
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Pin location as annotation on map
NSString *dateString = [NSDateFormatter localizedStringFromDate:[NSDate date]
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterFullStyle];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
MKUserLocation *userLocation = [[MKUserLocation alloc] init];
MKMapView *mapView = [[MKMapView alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"Picture Entry";
point.subtitle = dateString;
[mapView addAnnotation:point];
// Close camera and go back to home screen
[self dismissModalViewControllerAnimated:YES];
}
I'm new to iOS programming and I'm not sure how to pass the location back to my mapView, and I believe in this code I'm just initializing a new map to save the annotation to, and thats not what I want obviously.
MapViewController.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#end
MapViewController.m
#import "MapViewController.h"
#interface MapViewController ()
#end
#implementation MapViewController
#synthesize mapView;
- (void)viewDidLoad
{
// Get user location
mapView.showsUserLocation = YES;
self.mapView.delegate = self;
}
// Update map based on user location and zoom to area
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:
(MKUserLocation *)userLocation
{
mapView.centerCoordinate = userLocation.location.coordinate;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
#end
This is what I have for now, and I'm at a loss for how to handle this.
I believe in this code I'm just initializing a new map to save the annotation to, and thats not what I want obviously.
You're right -- you're creating a new map and adding the annotation to that object. (Also, you're not creating the map view correctly -- you should use -initWithFrame: because that's a designated initializer for views.)
You should rethink your approach. What you seem to be trying to do is to modify the map view of one view controller (your MapViewController) from a different view controller (assuming that the image picker delegate is some view controller other than MapViewController). A view controller should be in charge of its own views but shouldn't mess with the views of another view controller. Also, adding the annotation that way means that you're effectively storing the location in the map view, and you should avoid using views to store data.
Instead, think about where you should really be saving your data. The M in MVC is for model, i.e. that part of your app that manages the data. As you can see in the acronym, it should be separate from your view(s) and from your controller(s). The model is something that your various view controllers can all use to get the information they need, and having one makes your app simpler because you don't have to worry as much about sending data back and forth between view controllers. The model doesn't have to be anything terribly complicated -- for very simple apps that mainly manage a list of items, even an plain old NSArray or NSSet could serve as a data model. Give each view controller that needs it a reference to the model, or to part of the model.
With that in mind, the right way to fix your app is to have some sort of data model. The image picker delegate should update the map by adding information to the model. The map view controller should be in charge of adding annotations to the map view, and it can do that based on the information in the model.
Everytime I start the app, the first time seeing the map results in a default map that is always zoomed out with no annotations. When I go back on the navigation controller and go back into the map, it now shows the correct region with the appropriate pins. The code I use to add the
- (void) zoomIn {
mapView.showsUserLocation = YES;
CLLocationCoordinate2D annotation;
annotation.latitude = 47.640071;
annotation.longitude = -122.129598;
MKPointAnnotation *annoPoint = [[MKPointAnnotation alloc] init];
annoPoint.coordinate = annotation;
annoPoint.title = #"name";
[mapView addAnnotation:annoPoint];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(annotation, 500, 500);
[mapView setRegion:region animated:YES];
}
I call this block of code from the viewDidLoad, but it only works after I go back to the main page from the navigation controller and enter this UIViewController again.
Does anyone know what the problem is or have seen it before?
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// this delegate fonction is called when the userlocation is updated
// try to move your code here
}
you have also
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
}
hope this helps
Show us your viewDidLoad function, you're probably calling zoomIn too early, maybe before your MKMapView has been initialized.
I've looked at several StackOverflow posts and Apple documentation on how to implement overlays in MKMapView. For me, I'm interested specifically in displaying MKPolygon objects on my map. I've found that fundamentally, the process boils down to the following:
Link to MapKit and CoreLocation frameworks
Make an outlet to an MKMapKit object and declare view controller as delegate
Declare a CLLocationCoordinate2D array containing the points of a polygon and create an MKPolygon object with the class method polygonWithCoordinates:count:
Call addOverlay: of map and pass the newly created MKPolygon object as the parameter
Implement (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay
Later on, I'll likely be having to display 20-30 polygons at a given time on the map. However, in my exploration of how to display overlays (hardcoding test examples right now, rather than reading in data from a file), I've found that I can get some overlays to appear, but not others. Reading the Location Awareness Programming Guide by Apple, I came across an example of a polygon overlaid above the state of Colorado. That worked. But when I tried to make a polygon that covered Kansas, I couldn't get it to work. It seems that any polygon that I tried to make on my own (Embry-Riddle Aeronautical University polygon and Kansas polygon) won't display, but those that I got online work perfectly. I used Google Earth to create the polygons and then exported them as KML files to get the coordinates.
Code for the implementation of my ViewController is below. Just trying to find out what I may be unintentionally doing wrong to create this problem. Thanks in advance for help.
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Array of coordinates for polygon covering state of Colorado ... DISPLAYS PERFECTLY
CLLocationCoordinate2D points[4];
points[0] = CLLocationCoordinate2DMake(41.000512, -109.050116);
points[1] = CLLocationCoordinate2DMake(36.99892, -109.045267);
points[2] = CLLocationCoordinate2DMake(36.993076, -102.041981);
points[3] = CLLocationCoordinate2DMake(41.002371, -102.052066);
MKPolygon *polygon = [MKPolygon polygonWithCoordinates:points count:4];
[mapView addOverlay:polygon];
[polygon release];
// Array of coordinates for polygon covering state of Kansas ... DOESN'T DISPLAY
CLLocationCoordinate2D kansasPoints[9];
kansasPoints[0] = CLLocationCoordinate2DMake(-102.0595440241806, 39.99774930940907);
kansasPoints[1] = CLLocationCoordinate2DMake(-102.0424467175215, 36.99846609483674);
kansasPoints[2] = CLLocationCoordinate2DMake(-94.62550551403953, 36.98936020770036);
kansasPoints[3] = CLLocationCoordinate2DMake(-94.58798745384412, 39.11683771419185);
kansasPoints[4] = CLLocationCoordinate2DMake(-94.79955391183, 39.21290793052091);
kansasPoints[5] = CLLocationCoordinate2DMake(-95.13489191971419, 39.51613476830012);
kansasPoints[6] = CLLocationCoordinate2DMake(-94.86553124171813, 39.78380472206268);
kansasPoints[7] = CLLocationCoordinate2DMake(-95.02618283417986, 39.89072859904893);
kansasPoints[8] = CLLocationCoordinate2DMake(-95.31904155494097, 39.99390420513669);
MKPolygon *kansasPolygon = [MKPolygon polygonWithCoordinates:kansasPoints count:9];
[mapView addOverlay:kansasPolygon];
[kansasPolygon release];
// Array of coordinates for polygon covering part of Daytona Beach, FL campus
// of Embry-Riddle Aeronautical University... DOESN'T DISPLAY
CLLocationCoordinate2D erauPoints[7];
erauPoints[0] = CLLocationCoordinate2DMake(-81.05176, 29.18492);
erauPoints[1] = CLLocationCoordinate2DMake(-81.04409, 29.18801);
erauPoints[2] = CLLocationCoordinate2DMake(-81.05166, 29.19293);
erauPoints[3] = CLLocationCoordinate2DMake(-81.05365, 29.19536);
erauPoints[4] = CLLocationCoordinate2DMake(-81.05465, 29.19493);
erauPoints[5] = CLLocationCoordinate2DMake(-81.05376, 29.19323);
erauPoints[6] = CLLocationCoordinate2DMake(-81.05506, 29.19188);
MKPolygon *erauPolygon = [MKPolygon polygonWithCoordinates:erauPoints count:7];
[mapView addOverlay:erauPolygon];
[erauPolygon release];
// Array of coordinates taken from http://www.shawngrimes.me/2011/04/adding-polygon-map-overlays/
// for commuter parking lot at Capitol College in Maryland ... DISPLAYS PERFECTLY
CLLocationCoordinate2D commuterLotCoords[5]={
CLLocationCoordinate2DMake(39.048019,-76.850535),
CLLocationCoordinate2DMake(39.048027,-76.850234),
CLLocationCoordinate2DMake(39.047407,-76.850181),
CLLocationCoordinate2DMake(39.047407,-76.8505),
CLLocationCoordinate2DMake(39.048019,-76.850535)
};
MKPolygon *commuterPoly1 = [MKPolygon polygonWithCoordinates:commuterLotCoords count:5];
[mapView addOverlay:commuterPoly1];
[commuterPoly1 release];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolygon class]]) {
MKPolygonView *polygonView = [[[MKPolygonView alloc] initWithOverlay:overlay] autorelease];
polygonView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.3f];
polygonView.strokeColor = [UIColor redColor];
polygonView.lineWidth = 1.0f;
return polygonView;
}
return nil;
}
#end
It looks like the latitude and longitude parameters of the coordinates for the polygons that don't display are backwards.
For example, this:
kansasPoints[0] = CLLocationCoordinate2DMake(-102.0595440241806, 39.99774930940907);
should be
kansasPoints[0] = CLLocationCoordinate2DMake(39.99774930940907, -102.0595440241806);
Also, you should not be calling release on the MKPolygon objects you are creating using polygonWithCoordinates since they will be autoreleased.