I have the users location on my app, but how would I drop an annotation on the current user location? Would I have to get the long & lat of the users location and drop an annotation that way? or how would I do it?
First import the necessary frameworks (CoreLocation and MapKit).
Then create the Objective-C NSObject class Annotation
Setup its .h:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface Annotation : NSObject <MKAnnotation>
#property (nonatomic) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
Setup its .m:
#import "Annotation.h"
#implementation Annotation
#synthesize coordinate, title, subtitle;
#end
Setup viewDidLoad
if ([CLLocationManager locationServicesEnabled]) {
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy: kCLLocationAccuracyBestForNavigation];
[locationManager startUpdatingLocation];
}
self.mapView.delegate = self;
Setup the didUpdateToLocation
// IMPORT ANNOTATION
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
[locationManager stopUpdatingLocation];
double miles = 3.10686;
double scalingFactor = ABS((cos(2 * M_PI * newLocation.coordinate.latitude / 360.0)));
MKCoordinateSpan span;
span.latitudeDelta = miles/69.0;
span.longitudeDelta = miles/(scalingFactor * 69.0);
MKCoordinateRegion region;
region.span = span;
region.center = newLocation.coordinate;
[self.mapView setRegion:region animated:YES];
Annotation *annot = [[Annotation alloc] init];
annot.coordinate = newLocation.coordinate;
[self.mapView addAnnotation:annot];
}
The simplest way is to set showsUserLocation to YES on your MKMapView and implement
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region = MKCoordinateRegionMake(userLocation.location.coordinate, MKCoordinateSpanMake(0.01, 0.01));
[mapView setRegion:region animated:NO];
}
in your MKMapViewDelegate to have the map view move to that location when the user's location has been found.
This will show a blue dot on the map view at the user's location like the Maps app does.
Related
I have used map in my view controller but when the maps loads it shows me view of the whole country. I want to show my current location view when maps loads, for that I have used didUpdateUserLocation method and set delegate for it.
My code is this:
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
[self.mapView setRegion:MKCoordinateRegionMake(_userLocation.coordinate, MKCoordinateSpanMake(0.1f, 0.1f)) animated:YES];
}
Now when my map loads it animate and zoom but in wrong location. It is taking me to any location in sea when map loads , but my current location is different.
I have also tested it in real device but it does not show my location.
The maps looks like that when loads:
ViewController class code:
#property BOOL updateUserLocation;
#property(strong,nonatomic) CLLocation *userLocation;
#property (nonatomic, retain) MKPolyline *routeLine;
#property (nonatomic, retain) MKPolylineView *routeLineView;
#property (nonatomic,retain) NSString *latitude;
#property (nonatomic,retain) NSString *longitude;
- (void)viewDidLoad {
[super viewDidLoad];
[[self navigationController] setNavigationBarHidden:YES animated:YES];
_AlertView.hidden=YES;
_distanceView.hidden=YES;
self.mapView.zoomEnabled=YES;
locationManager = [[CLLocationManager alloc]init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
[self.mapView setShowsUserLocation:YES];
[self.mapView setDelegate:self];
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
[self.mapView setRegion:MKCoordinateRegionMake(_userLocation.coordinate, MKCoordinateSpanMake(0.1f, 0.1f)) animated:YES];
}
Add these lines in the viewDidLoad:
self.mapView.showsUserLocation = YES;
if you want to center the map to the user location add this:
[self.mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
EDIT:
ViewController example:
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController () <CLLocationManagerDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) CLLocation *location;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[self mapView] setShowsUserLocation:YES];
self.locationManager = [[CLLocationManager alloc] init];
// we have to setup the location manager with permission in later iOS versions
if ([[self locationManager] respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[[self locationManager] requestWhenInUseAuthorization];
}
[[self locationManager] setDelegate:self];
[[self locationManager] setDesiredAccuracy:kCLLocationAccuracyBest];
[[self locationManager] startUpdatingLocation];
}
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
// Stop updating location, when you want to restart update use [[self locationManager] startUpdatingLocation];
[manager stopUpdatingLocation];
self.location = locations.lastObject;
// zoom the map into the users current location
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance
(self.location.coordinate, 2, 2);
[[self mapView] setRegion:viewRegion animated:YES];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I've only added the IBOutlet on the storyboard and the NSLocationWhenInUseUsageDescription key in the plist.
If you change the location on the simulator you can see the maps change location.
If you want I can upload the complete example project.
NEW EDIT:
There is an error in you code!
When you use [self.mapView setRegion:MKCoordinateRegionMake(_userLocation.coordinate, MKCoordinateSpanMake(0.1f, 0.1f)) animated:YES], you use _userLocation that is your CLLocation variable! You must use userLocation that is the value that you receive from the method.
I recommend you to change the CCLocation variable name and use the userLocation name only for the variable used in the didUpdateUserLocation method.
You can call this method and zoom on map
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = ; // your latitude value
zoomLocation.longitude= // your longitude value
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.18; // change as per your zoom level
span.longitudeDelta=0.18;
region.span=span;
region.center= zoomLocation;
[mapview setRegion:region animated:TRUE];
[mapview regionThatFits:region];
Use didUpdateToLocation instead of didUpdateUserLocation.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
[self.locationManager stopUpdatingLocation];
MKCoordinateRegion region;
region.span.latitudeDelta = 0.005;
region.span.longitudeDelta = 0.005;
region.center.latitude = newLocation.coordinate.latitude;
region.center.longitude = newLocation.coordinate.longitude;
[self.mapView setRegion:region animated:YES];
}
See also my library.
https://github.com/koogawa/KGWLocationPicker/blob/master/KGWLocationPicker/KGWLocationPickerViewController.m
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;
//}
}
I can't understand how CLLocationManager get my current location coordinates ? if I don't call [locationManager startUpdatingLocation] and don't set parameters in locationManager.location.coordinate.
ViewController.h
#interface ViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
}
#property (weak, nonatomic) IBOutlet MKMapView* mapView;
#end
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
-(void) mapView:(MKMapView *) mv didAddAnnotationViews:(NSArray *)views {
MKCoordinateRegion region;
region = MKCoordinateRegionMakeWithDistance(locationManager.location.coordinate, 1000, 1000);
[mv setRegion:region animated:YES];
}
Most likely it's a cached value after MapView requested current location update because of the following line:
[self.mapView setShowsUserLocation:YES];
I'm trying to zoom into the user location as the center reference for the screen. I have this code:
MainViewController.h
#import <UIKit/UIKit.h>
#import "FlipsideViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
IBOutlet MKMapView *mapView;
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate, MKMapViewDelegate> {
MKMapView *mapView;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
MainViewController.m
#implementation MainViewController
#synthesize mapView;
- (void)viewDidLoad {
[super viewDidLoad];
mapView = [[MKMapView alloc]
initWithFrame:self.view.bounds
];
mapView.showsUserLocation = YES;
mapView.mapType = MKMapTypeHybrid;
mapView.delegate = self;
[self.view addSubview:mapView];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.005;
span.longitudeDelta = 0.005;
CLLocationCoordinate2D location;
location.latitude = userLocation.coordinate.latitude;
location.longitude = userLocation.coordinate.longitude;
region.span = span;
region.center = location;
[mapView setRegion:region animated:YES];
}
Now I'm only getting a build warning on the last line [mapView setRegion:region animated:YES] stating: 'local declaration of 'mapView' hides instance variable'
When you do mapView.showsUserLocation = YES;, you ask it to retrieve the user location. This doesn't happen instantly. As it takes time, the map view notifies its delegate that a user location is available via the delegate method mapView:didUpdateUserLocation. So you should adopt the MKMapViewDelegate protocol and implement that method. You should move all your zooming-in code to this method.
Setting the delegate
- (void)viewDidLoad {
[super viewDidLoad];
mapView = [[MKMapView alloc]
initWithFrame:CGRectMake(0,
0,
self.view.bounds.size.width,
self.view.bounds.size.height)
];
mapView.showsUserLocation = YES;
mapView.mapType = MKMapTypeHybrid;
mapView.delegate = self;
[self.view addSubview:mapView];
}
Updated delegate method
- (void)mapView:(MKMapView *)aMapView didUpdateUserLocation:(MKUserLocation *)aUserLocation {
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;
[aMapView setRegion:region animated:YES];
}
In your interface you forgot to inherit MapViewDelegate -
#import <MapKit/MapKit.h>
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate, MKMapViewDelegate>
{
MKMapView *mapView;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
Rest seems fine.
I need help with showing the user's location on my MapView. I have done everything I could possibly find online, but it still does not work.
I have a CLLocationManager in my AppDelegate that calls the locationUpdate in my viewController.
The (void)locationUpdate:(CLLocation *)location method gets called every time and the location coordinates is correct when logged with the NSLog(). Still, there is no "Blue Dot" on my iPhone's screen. The region is not set as well.
Please take a look and tell me if I am missing anything.
This is my header file:
//My .h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotation.h>
#import <MapKit/MKReverseGeocoder.h>
#interface FirstViewController : UIViewController <MKMapViewDelegate>
{
MKMapView *mapView;
}
-(void)locationUpdate:(CLLocation *)location;
-(void)locationError:(NSError *)error;
#end
This is my part of my implementation file:
//My .m file
#import "FirstViewController.h"
#implementation FirstViewController
- (void)viewDidLoad
{
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.showsUserLocation = YES;
mapView.mapType = MKMapTypeStandard;
mapView.delegate = self;
CLLocationCoordinate2D location;
MKCoordinateRegion region;// = {{0.0,0.0},{0.0,0.0}};
location.latitude = -33.8771;
location.longitude = 18.6155;
MKCoordinateSpan span;
span.latitudeDelta = 0.01;
span.longitudeDelta = 0.01;
region.span = span;
region.center = location;
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
[super viewDidLoad];
}
-(void)locationUpdate:(CLLocation *)location
{
CLLocationCoordinate2D loc = [location coordinate];
[mapView setCenterCoordinate:loc];
if([mapView showsUserLocation] == NO)
[mapView setShowsUserLocation:YES];
NSLog(#"User Loc: %f, %f", mapView.userLocation.location.coordinate.latitude,
mapView.userLocation.location.coordinate.longitude);
NSLog(#"In MapView: %#",[location description]);
}
#end
Thank you for your time!
It is much appreciated!
Your Map kit in Interface Builder needs to have the (Find User Location) checked!!