Scrolling around my current position in MKMapView - ios

Following Online tutorials I made a MKMapView working, but I have a couple of problems:
First problem: Map show my current position, but if I try to scroll that map It will automatically return to my position, so, for example, I am not able to see what streets are nearby, because map will center back to my current position.
Second problem: I'd like to implement some "pinch to zoom" as if you tap on my map it will get that tap point's longitude and latitude.
I surely messed up my code, because I mixed two tutorial in one ... trying to archive what I needed from my "app". :-)
This is in my .h:
#interface mappa2 : UIViewController <CLLocationManagerDelegate> {
MKMapView *mapview;
CLLocationManager *manager;
CLGeocoder *geocoder;
CLPlacemark *placemark;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapview;
And this is my messy .m
#synthesize mapview;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Procedura per TAP:
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(foundTap:)];
tapRecognizer.numberOfTapsRequired = 1;
tapRecognizer.numberOfTouchesRequired = 1;
[self.mapview addGestureRecognizer:tapRecognizer];
[self startMap]; }
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"Errore %#",error);
NSLog(#"Non ho potuto calcolare la posizione");
}
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(#"Location: %#",newLocation);
CLLocation *currentLocation = newLocation;
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] >0 ) {
placemark = [placemarks lastObject];
}
else NSLog(#"%#",error.debugDescription);
}];
MKCoordinateRegion region = { {0.0, 0.0}, {0.0, 0.0} };
region.center.latitude = currentLocation.coordinate.latitude;
region.center.longitude = currentLocation.coordinate.longitude;
region.span.longitudeDelta = 0.001f;
region.span.latitudeDelta = 0.001f;
[mapview setRegion: region animated:YES];
[mapview setScrollEnabled:YES];
}
- (void) startMap {
manager = [[CLLocationManager alloc] init];
geocoder = [[CLGeocoder alloc] init];
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyBest;
[manager startUpdatingLocation];
mapview.mapType = MKMapTypeStandard;
mapview.showsUserLocation = YES;
}
So .. I'd like that my map could point to my current position when "view did load", but then I'd be able to move around that point! ... and zooming in and out with gesture... is that too much for a newbie?
Thank in advance!

For the first issue, you're probably updating and resetting your location via MKMapView delegate.
Mk Mapview keeps resetting on users location?
For the second issue, the question probably contains the answer you are looking for. If not, the answers have it, plus extra code, for sure.
Get the coordinates of a point from mkmapview on iphone

Related

how to show a map with a single annotation and the users location and have the map display both whether the user is 100ft or 100miles

I'd like to have a map with just two points, the users location and a single annotation (it's for a pov). I have included what I
have below. Ideally, I would like it to handle if the user is 100 feet away or 100 miles in displaying both the User and the annotation in
the map view. I think it would be best if the location were at the center and the user were on the edge with some reasonable 20% buffer on the edge of the map view. I only need to support iOS 7 and greater.
Is there something like sizeToFit for annotations that takes into account users position as an annotation?
my MapViewController.h
#interface MapViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
my MapViewController.m:
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
#import "MapViewController.h"
#import "MYUtility.h"
#interface MapViewController (){
NSMutableArray *_yourAnnotationArray;
MKPointAnnotation *_locationPoint;
BOOL _firstTime;
}
#end
#implementation MapViewController
- (void)viewDidLoad {
[super viewDidLoad];
_firstTime=YES;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if(IS_OS_8_OR_LATER) {
//[self.locationManager requestWhenInUseAuthorization];
//[self.locationManager requestAlwaysAuthorization];
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager startUpdatingLocation];
}
[self.locationManager startUpdatingLocation];
[self.mapView setShowsUserLocation:YES];
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
CGFloat latitude=MYLocationLatitude();
CGFloat longitude=MYLocationLongitude();
_locationPoint = [[MKPointAnnotation alloc] init];
_locationPoint.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
_locationPoint.title = #"Where am I?";
_locationPoint.subtitle = #"I'm here!!!";
[self.mapView addAnnotation:_locationPoint];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//if(_firstTime){
NSLog(#"here is my thinking %#", [locations lastObject]);
[self setMapStart];
}
-(void)setMapStart
{
//if(_firstTime){
NSLog(#"at top of _firstTime being true");
MKPointAnnotation *myPoint = [[MKPointAnnotation alloc] init];
myPoint.coordinate = CLLocationCoordinate2DMake(34.035645, -118.233434);
MKMapPoint annotationPoint = MKMapPointForCoordinate(self.mapView.userLocation.coordinate);
//[_yourAnnotationArray addObject:annotationPoint];
_yourAnnotationArray=[[NSMutableArray alloc] initWithObjects:_locationPoint,annotationPoint, nil];
//NSLog(#"here is my count: %i",(unsigned long)[_yourAnnotationArray count]);
[self.mapView showAnnotations:self.mapView.annotations animated:YES]; // <- determine when this has run
_firstTime=NO;
//}
}

Can't get user location with iOS MapKit

Getting the user location to work has been killing me...
I've read lots of threads explaining the new changes with iOS 8 and how there must be one of two keys (NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription) in the info.plist file in order for the app to ask permission to get user location. I did that.
I've also included what I believe as all the code needed for the location service to work...but it doesn't. Please see my mapViewController.h and mapViewController.m files below:
mapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotation.h>
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
#interface mapViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
#property(nonatomic, retain) IBOutlet MKMapView *mapView;
#property(nonatomic, retain) CLLocationManager *locationManager;
#end
mapViewController.m
#import "mapViewController.h"
#interface mapViewController ()
#end
#implementation mapViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.mapView.delegate = self;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER) {
// Use one or the other, not both. Depending on what you put in info.plist
//[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
#endif
[self.locationManager startUpdatingLocation];
self.mapView.showsUserLocation = YES;
[self.mapView setMapType:MKMapTypeStandard];
[self.mapView setZoomEnabled:YES];
[self.mapView setScrollEnabled:YES];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
self.locationManager.distanceFilter = kCLDistanceFilterNone; //Whenever we move
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
NSLog(#"%#", [self deviceLocation]);
//View Area
MKCoordinateRegion region = { { 0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = self.locationManager.location.coordinate.latitude;
region.center.longitude = self.locationManager.location.coordinate.longitude;
region.span.longitudeDelta = 0.005f;
region.span.longitudeDelta = 0.005f;
[self.mapView setRegion:region animated:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
- (NSString *)deviceLocation {
return [NSString stringWithFormat:#"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceLat {
return [NSString stringWithFormat:#"%f", self.locationManager.location.coordinate.latitude];
}
- (NSString *)deviceLon {
return [NSString stringWithFormat:#"%f", self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceAlt {
return [NSString stringWithFormat:#"%f", self.locationManager.location.altitude];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Also, in case this is relevant, the mapViewController is tied to a tab in a Tab View Controller. When I click on the tab that includes the view controller containing MKMapView, I get the below image:
Use this code and run the application in device to get the current location.
If you run in simulator, then it will show the default location i.e Apple Inc's address as current location.
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self ];
self.mapView.showsUserLocation=YES;
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[self.mapView setCenterCoordinate:newLocation.coordinate animated:YES];
MKCoordinateRegion region=MKCoordinateRegionMakeWithDistance(newLocation.coordinate,70000 ,70000 );
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:region];
[self.mapView setRegion:adjustedRegion animated:YES];
}
Note:
Turn on data or wifi in your device, or else you will face Location Accuracy error.
Add the below code to your ViewController.h class,
#interface ViewController : UIViewController<CLLocationManagerDelegate>
#property(nonatomic, retain) CLLocationManager *locationManager;
#end
And in ViewController.m class ,
-(void)viewWillAppear:(BOOL)animated{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
[super viewWillAppear:animated];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D zoomLocation = CLLocationCoordinate2DMake(newLocation.coordinate.latitude, newLocation.coordinate.longitude);
}
Per the docs, [self.locationManager requestAlwaysAuthorization] is asynchronous. Implement the location services auth changed delegate callback and start monitoring there only after the auth status is allowed.

GPS Tracking in Xcode stopped working in Xcode 6 after working in Xcode 5

I am going through a tutorial on youtube that teaches you how to track and trace a user's location on a map view. The tutorial comes with a copy of the code so I downloaded the code files and opened them up in Xcode. The first time that I opened the code in Xcode I had the newest Xcode 5. It ran just fine finding and tracing the location. About a day later Xcode 6 came out so I updated my Xcode to Xcode 6. When opening the code files in Xcode 6, the application would not preform correctly. I am getting an error that says...
2014-09-28 17:24:34.468 GPSTrack[1644:130866] Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.
In the header file GPSTrackerViewController.h
//
// GPSTrackViewController.h
// GPSTrack
//
// Created by Nick Barrowclough on 4/21/14.
// Copyright (c) 2014 iSoftware Developers. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h> //import the mapkit framework
#interface GPSTrackViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate, MKOverlay> {
CLLocationManager *lm; //core lcoation manager instance
NSMutableArray *trackPointArray; //Array to store location points
//instaces from mapkit to draw trail on map
MKMapRect routeRect;
MKPolylineView* routeLineView;
MKPolyline* routeLine;
}
- (IBAction)startTracking:(id)sender;
- (IBAction)stopTracking:(id)sender;
- (IBAction)clearTrack:(id)sender;
#property (weak, nonatomic) IBOutlet MKMapView *mapview;
#end
GPSTrackViewController.m
//
// GPSTrackViewController.m
// GPSTrack
//
// Created by Nick Barrowclough on 4/21/14.
// Copyright (c) 2014 iSoftware Developers. All rights reserved.
//
#import "GPSTrackViewController.h"
#interface GPSTrackViewController ()
#end
#implementation GPSTrackViewController
#synthesize mapview;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
mapview.mapType = MKMapTypeHybrid;
}
- (void)viewWillAppear:(BOOL)animated {
trackPointArray = [[NSMutableArray alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)startTracking:(id)sender {
//start location manager
lm = [[CLLocationManager alloc] init];
lm.delegate = self;
lm.desiredAccuracy = kCLLocationAccuracyBest;
lm.distanceFilter = kCLDistanceFilterNone;
[lm startUpdatingLocation];
mapview.delegate = self;
mapview.showsUserLocation = YES;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
//get the latest location
CLLocation *currentLocation = [locations lastObject];
//store latest location in stored track array;
[trackPointArray addObject:currentLocation];
//get latest location coordinates
CLLocationDegrees Latitude = currentLocation.coordinate.latitude;
CLLocationDegrees Longitude = currentLocation.coordinate.longitude;
CLLocationCoordinate2D locationCoordinates = CLLocationCoordinate2DMake(Latitude, Longitude);
//zoom map to show users location
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(locationCoordinates, 1000, 1000);
MKCoordinateRegion adjustedRegion = [mapview regionThatFits:viewRegion]; [mapview setRegion:adjustedRegion animated:YES];
NSInteger numberOfSteps = trackPointArray.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [trackPointArray objectAtIndex:index];
CLLocationCoordinate2D coordinate2 = location.coordinate;
coordinates[index] = coordinate2;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[mapview addOverlay:polyLine];
//NSLog(#"%#", trackPointArray);
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor redColor];
polylineView.lineWidth = 4.0;
return polylineView;
}
- (IBAction)stopTracking:(id)sender {
//reset location manager and turn off GPS
lm = [[CLLocationManager alloc] init];
[lm stopUpdatingLocation];
lm = nil;
//stop shwing user location
mapview.showsUserLocation = NO;
//reset array fo tracks
trackPointArray = nil;
trackPointArray = [[NSMutableArray alloc] init];
}
- (IBAction)clearTrack:(id)sender {
//remove overlay on mapview
[mapview removeOverlays: mapview.overlays];
}
#end
Can someone please help me understand why the application is not running any more and give me some suggestions of what I need to do to get it up and running again.
under base sdk 8 (which is what xcode 6 uses, I removed the xcode tag as it isn't IDE specific) you have to ask for authorisation first and have to have a plist key (a string saying why you need to use GPS)
the plist key depends on your needs is EITHER
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
this SO question looks good:
IOS 8 CLLocationManager Issue (Authorization Not Working)
for detailed instructs, I can recommend (skimmed it):
http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/

Google maps gives current position arrow but doesn't load the map

I dropped the maps from iOS and switched to google maps. Now it shows my position but it doesn't load the map. It is gray / yellow with in the bottom left Google.
This is my implementation:
#import <CoreLocation/CoreLocation.h>
#interface GoogleMapViewController ()
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#implementation GoogleMapViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Create a GMSCameraPosition that tells the map to display the
// coordinate -33.86,151.20 at zoom level 6.
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86
longitude:151.20
zoom:6];
_mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
_mapView.myLocationEnabled = YES;
self.view = _mapView;
[self initLocationManager];
// Creates a marker in the center of the map.
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(-33.86, 151.20);
marker.title = #"Sydney";
marker.snippet = #"Australia";
marker.map = _mapView;
}
- (void) initLocationManager
{
self.locationManager = [[CLLocationManager alloc] init] ;
self.locationManager.delegate = (id)self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation ;
[self.locationManager setDistanceFilter:10.0f] ;
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"New locations");
[self.locationManager stopUpdatingLocation];
_mapView.camera = [GMSCameraPosition cameraWithTarget:newLocation.coordinate
zoom:6];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
This is basically the tutorial demo app from Google Dev page, and I'm not sure why it's not loading the map.
This is what I get:
I found the problem. You need to set the initial camera zoom level on 1 and then zoom in on your current location. That way you can still zoom out and have the whole map available.
If you take a zoomlevel 14 as initial, google maps doesn't load the rest of the map I think.

Open Detail View from Annotation

I have a map view with several annotations. Each annotation has a button that takes the user to a detail view for that annotation. The detail view currently has two labels, one for the title from the annotation and the other for the subtitle of the annotation, and a "Get Directions" button. I want the title label to be populated with the title from the annotation and the subtitle label to be populated with the subtitle from the annotation. I want the Get Directions button to take the user into the Maps app and give them directions to the address from their current location. I'd also like to add website and phone number to the detail view but I'm not sure how to populate those fields either. The detail view is called AnnotationDetailView but I haven't done anything with it besides add the button and labels in IB. I'm just not sure how to populate the labels and get the button doing what I want. Any help would be great.
Here is my code:
//
// RSFM.m
#import "RSFM.h"
#import "AnnotationDetailView.h"
#interface RSFM ()
#end
#implementation RSFM
{
}
#synthesize centerCoordinate, coordinate, title, subtitle;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.title = NSLocalizedString(#"Farm Markets", #"Farm Markets");
// Create location manager object
locationManager = [[CLLocationManager alloc]init];
[locationManager setDelegate:self];
// And we want it to be as accurate as possible regardless of how much time/power it takes
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
// Tell our manager to start looking for its location immediately
// [locationManager startUpdatingLocation];
}
return self;
}
/*
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
{
centerCoordinate = CLLocationCoordinate2DMake(37.7885, 85.3279);
}
*/
- (void)findLocation
{
[locationManager startUpdatingLocation];
[activityIndicator startAnimating];
// [locationTitleField setHidden:YES];
[locationManager stopUpdatingLocation];
}
- (void)foundLocation:(CLLocation *)loc
{
CLLocationCoordinate2D coord = [loc coordinate];
// Create an instance of BNRMapPoint with the current data
// BNRMapPoint *mp = [[BNRMapPoint alloc]initWithCoordinate:coord title:[locationTitleField text]];
// Add it to the map view
// [worldView addAnnotation:mp];
// Zoom the region to this location
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coord, 700000, 700000);
[worldView setRegion:region animated:YES];
// Reset the UI
// [locationTitleField setText:#""];
[activityIndicator stopAnimating];
// [locationTitleField setHidden:NO];
[locationManager stopUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"%#", newLocation);
// How many seconds ago was this new location created?
NSTimeInterval t = [[newLocation timestamp]timeIntervalSinceNow];
// CLLocationManagers will return the last found location of the device first, you don't want that data in this case.
// If this location was made more than 3 minutes ago, ignore it.
if (t < -180)
{
// this is cached data, you don't want it, keep looking
return;
}
[self foundLocation:newLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"Could not find location: %#", error);
}
- (void)dealloc
{
// Tell the location manager to stop sending us messages
[locationManager setDelegate:nil];
}
- (IBAction)showDetails:(id)sender
{
AnnotationDetailView *detail = [[AnnotationDetailView alloc] initWithNibName:nil bundle:nil];
detail.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:detail animated:YES];
}
- (MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// If it's the user location, return nil
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Try to dequeue an existing pin view first
static NSString *annotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
return pinView;
}
- (void)viewDidLoad
{
[locationManager startUpdatingLocation];
[worldView setShowsUserLocation:YES];
[locationManager stopUpdatingLocation];
NSMutableArray *marketLocations = [[NSMutableArray alloc]init];
NSMutableArray *lat = [[NSMutableArray alloc]initWithObjects:#"37.7867266", #"37.0703517", #"37.1610806", #"37.318367", #"37.3559204", #"37.4154066", #"37.4757622", #"37.7450252", #"37.6318978", #"37.0716803", nil];
NSMutableArray *lon = [[NSMutableArray alloc]initWithObjects:#"-87.608209", #"-88.1237899", #"-87.9148629", #"-87.5074402", #"-87.5448032", #"-87.8003148", #"-87.9515986", #"-87.9061638", #"-87.1148574", #"-87.3008418", nil];
NSMutableArray *title1 = [[NSMutableArray alloc]initWithObjects:#"Cates Farm", #"Broadbent B & B Foods", #"Cayce's Pumpkin Patch", #"Metcalfe Landscaping", #"Brumfield Farm Market", #"Dogwood Valley Farm", #"Country Fresh Meats & Farmers Market", #"Jim David Meats", #"Trunnell's Farm Market", #"Lovell's Orchard & Farm Market", nil];
NSMutableArray *subtitle1 = [[NSMutableArray alloc]initWithObjects:#"Hwy 425 Henderson, KY 42420", #"257 Mary Blue Road Kuttawa, KY 42055", #"153 Farmersville Road Princeton, KY 42445", #"410 Princeton Road Madisonville, KY 42431", #"3320 Nebo Road Madisonville, KY 42431", #"4551 State Route 109N Clay, KY 42404", #"9355 US Hwy 60 W Sturgis, KY 42459",#"350 T. Frank Wathen Rd. Uniontown, KY 42461", #"9255 Hwy 431 Utica, KY 42376", #"22850 Coal Creek Road Hopkinsville, KY 42240", nil];
CLLocationCoordinate2D location;
MKPointAnnotation *marketAnnotation;
for (int x = 0; x < [lat count]; x++)
{
marketAnnotation = [[MKPointAnnotation alloc]init];
location.latitude = [[lat objectAtIndex:x]floatValue];
location.longitude = [[lon objectAtIndex:x]floatValue];
marketAnnotation.coordinate = location;
marketAnnotation.title = [title1 objectAtIndex:x];
marketAnnotation.subtitle = [subtitle1 objectAtIndex:x];
[marketLocations addObject:marketAnnotation];
}
[worldView addAnnotations:marketLocations];
/*
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = CLLocationCoordinate2DMake(37.7867266, -87.608209);
point.title = #"Cates Farm";
point.subtitle = #"Hwy 425 Henderson, KY 42420";
[worldView addAnnotation:point];
*/
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
CLLocationCoordinate2D loc = [userLocation coordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 700000, 700000);
[worldView setRegion:region animated:YES];
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
}
- (IBAction)selectSegmentControl
{
int segmentTouched = [mapVarieties selectedSegmentIndex];
NSString *segmentName = [mapVarieties titleForSegmentAtIndex:segmentTouched];
if ([segmentName isEqualToString:#"Street"])
{
[worldView setMapType:MKMapTypeStandard];
}
if ([segmentName isEqualToString:#"Satellite"])
{
[worldView setMapType:MKMapTypeSatellite];
}
if ([segmentName isEqualToString:#"Hybrid"])
{
[worldView setMapType:MKMapTypeHybrid];
}
}
#end
Here is where I show the detail view
- (IBAction)showDetails:(id)sender
{
AnnotationDetailView *detail = [[AnnotationDetailView alloc] initWithNibName:nil bundle:nil];
detail.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
NSLog(#"%#", marketAnnotation.title);
detail.ti.text = marketAnnotation.title;
[self.navigationController pushViewController:detail animated:YES];
}
and the AnnotationDetailView
//
// AnnotationDetailView.m
#import "AnnotationDetailView.h"
#interface AnnotationDetailView ()
#end
#implementation AnnotationDetailView
#synthesize ti;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// [title setText:marketAnnotation.title];
// [subtitle setText:marketAnnotation.subtitle];
ti = [[UILabel alloc]initWithFrame:CGRectMake(20, 20, 281, 21)];
[self.view addSubview:ti];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I'm having a couple of issues with this. One, the label is not showing up. Two, I have an NSLog statement in my showDetails method to show me what marketAnnotations is. It is showing the title of the last annotation added.
You can add extra parameters to your MKAnnotation class. For example this Annotation class uses 3 extra strings to hold information:
// MyAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation>
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy, readonly) NSString *title;
#property (nonatomic, copy, readonly) NSString *subtitle;
#property (nonatomic, copy, readonly) NSString *myString1;
#property (nonatomic, copy, readonly) NSString *myString2;
#property (nonatomic, copy, readonly) NSString *myString3;
-(id)initWithCoordinates:(CLLocationCoordinate2D) paramCoordinates
title:(NSString *) paramTitle
subTitle:(NSString *) paramSubTitle
myString1:(NSString *) paramMyString1
myString2:(NSString *) paramMyString2
myString3:(NSString *) paramMyString3;
#end
// MyAnnotation.m
#import "MyAnnotation.h"
#implementation MyAnnotation
-(id)initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates
title:(NSString *)paramTitle
subTitle:(NSString *)paramSubTitle
myString1:(NSString *)paramMyString1
myString2:(NSString *)paramMyString2
myString3:(NSString *)paramMyString1
{
self = [super init];
if(self != nil)
{
_coordinate = paramCoordinates;
_title = paramTitle;
_subtitle = paramSubTitle;
_myString1 = paramMyString1;
_myString2 = paramMyString2;
_myString3 = paramMyString3;
}
return (self);
}
#end
When the user taps a pin, you can do this to pass information from the Annotation to the next View Controller:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
if ([(UIButton*)control buttonType] == UIButtonTypeDetailDisclosure)
{
YourViewController *vc = [[YourViewController alloc] init];
[vc setTitleString:[(MyAnnotation *)view.annotation title]];
[vc setSubTitleString:[(MyAnnotation *)view.annotation subTitle]];
[vc setPassedString1:[(MyAnnotation *)view.annotation myString1]];
[vc setPassedString2:[(MyAnnotation *)view.annotation myString2]];
[vc setPassedString3:[(MyAnnotation *)view.annotation myString3]];
[[self navigationController] pushViewController:vc animated:YES];
}
}
In your next View Controller (vc), you can modify the button text like this:
[myButton setTitle:myPassedString1 forState:UIControlStateNormal];

Resources