I am trying to use GoogleMap API and apple's CLocationManager for my app, but it does not show my current location in either of them.
I have set up the API in AppDelegate.m and also asking and checking user permission to track location. This is the code I have for map.
I am trying to get user's current location and I will get user's destination and notify them when they are close to their location (using both estimated time and distance). I would appreciate if you can help me about that too. thanks
#import "GMapViewController.h"
#import <GoogleMaps/GoogleMaps.h>
#import "CSMarker.h"
#import GoogleMaps;
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface GMapViewController () <GMSMapViewDelegate, CLLocationManagerDelegate, MKMapViewDelegate>
#property(strong, nonatomic) NSURLSession *markerSession;
#property(strong, nonatomic) GMSPolyline *polyline;
#property(strong, nonatomic) NSArray *steps;
//apple
#property (weak, nonatomic) IBOutlet MKMapView *mapViews;
#end
#implementation GMapViewController
#synthesize viewDirection,locationManager;
#synthesize mapView;
- (void)startStandardUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self startStandardUpdates];
self.mapView.delegate=self;
self.mapViews.delegate=self;
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
//map type
self.mapView.mapType = kGMSTypeNormal;
[self.view addSubview:self.mapView];
// to show compass and mylocation button
self.mapView.settings.compassButton = YES;
self.mapView.settings.myLocationButton = YES;
//setting max and min zoom
//[self.mapView setMinZoom:10 maxZoom:18];
//for Drawing a line on the map
GMSMutablePath *singleLinePath = [[GMSMutablePath alloc] init];
// create a GMSMutablePath and add two points as lat/lng
[singleLinePath addLatitude:28.5382 longitude:-81.3687];
[singleLinePath addLatitude:28.5421 longitude:-81.3690];
// use the path to create a GMSPolyline
GMSPolyline *singleLine = [GMSPolyline polylineWithPath:singleLinePath];
singleLine.map = self.mapView; //turn the line on
self.mapViews.showsUserLocation = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
NSString *errorType = nil;
if (error.code == kCLErrorDenied)
{errorType = #"Access Decied";}
else
{errorType = #"Unknown Error";}
UIAlertController* alert = [UIAlertController
alertControllerWithTitle: #"Alert"
message: #"Error getting location!"
preferredStyle: UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action)
{
NSLog(#"OK action");
}];
[alert addAction:okAction];
[self presentViewController:alert animated:YES completion:nil];
}
#end
Can you check if you have defined following keys in your info.plist? All three keys are not needed, you need to define one or two of these keys depending on your uses permissions.
NSLocationAlwaysUsageDescription: Always location description
NSLocationWhenInUseUsageDescription: When in use location description
NSLocationAlwaysAndWhenInUseUsageDescription: description for both
Take another look at your locationManager:(CLLocationManager *)manager didUpdateLocations: method. You are getting the newLocation reference, but it doesn't look like you do anything with it. Also, you do not appear to be setting the currentLocation value anywhere.
Related
I have been trying to make an app that allows the user to retrieve the current location using the core location framework. I wanted to be able to get the coordinates of the device that is using the app when the app launches and be able to display them using UILabels. Can someone please tell me what i am doing wrong or what adjustments I should make to the code?
Header file:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *longitude;
#property (strong, nonatomic) IBOutlet UILabel *latitude;
#property (strong, nonatomic) IBOutlet UILabel *altitude;
#property (strong, nonatomic) IBOutlet UILabel *speed;
#end
Implementation file:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
CLLocationManager *locationManager;
[super viewDidLoad];
locationManager = [[CLLocationManager alloc]init]; // initializing locationManager
locationManager.delegate = self; // I set the delegate of locationManager to self.
locationManager.desiredAccuracy = kCLLocationAccuracyBest; // setting the accuracy
[locationManager startUpdatingLocation]; //requesting location updates
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
UIAlertView *errorAlert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"There was an error retrieving your location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[errorAlert show];
NSLog(#"Error: %#",error.description);
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *crnLoc = [locations lastObject];
_latitude.text = [NSString stringWithFormat:#"%.8f",crnLoc.coordinate.latitude];
_longitude.text = [NSString stringWithFormat:#"%.8f",crnLoc.coordinate.longitude];
_altitude.text = [NSString stringWithFormat:#"%.0f m",crnLoc.altitude];
_speed.text = [NSString stringWithFormat:#"%.1f m/s", crnLoc.speed];
}
#end
I get these 2 errors.
Assigning to 'id<CLLocationManagerDelegate> _Nullable' from incompatible type 'ViewController *const __strong'
'UIAlertView' is deprecated: first deprecated in iOS 9.0 - UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead
You're not implementing the CLLocationManagerDelegate protocol, which is why you get the first error. You could implement it like this:
#interface ViewController () <CLLocationManagerDelegate>
#end
You should also check the documentation for the methods that you'll need to implement in order to conform to that protocol, which you'll have to write in your #implementation. Only after conforming to that protocol is this assignment allowed:
locationManager.delegate = self; // I set the delegate of locationManager to self.
The second issue appears to be a warning. Apple did deprecate UIAlertView in iOS 9.0 and it has been replaced by UIAlertController, so you should use that instead. This NSHipster article explains how to use and compares it with the old, deprecated, version, which is interesting, but it's in Swift (I'm leaving it for the discussion they present). Here you'll also find some examples in Objective-C. Here's an example as shown on that last link:
UIAlertController * view= [UIAlertController
alertControllerWithTitle:#"My Title"
message:#"Select you Choice"
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* ok = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
//Do some thing here
[view dismissViewControllerAnimated:YES
completion:nil];
}];
UIAlertAction* cancel = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[view dismissViewControllerAnimated:YES completion:nil];
}];
[view addAction:ok];
[view addAction:cancel];
[self presentViewController:view animated:YES completion:nil];
I have just begun development with 'objective candParse`.
I have a function in my app where I am allowing the user to enter in a new climb.
Data are stored in a table of mine in Parse. I add that climb into the map view portion of my app.
I am wanting to write a select statement that stores all of the results from the query into an array of some sort and then I will dump that into the map view portion. This way I am thinking that it will dynamically add a map pin to the map every time a new area is added, if it does not already exist of course.
I am a .net developer and in this scenario I would grab all the data and then dump it into a data table and real with it from there.... But I am not sure of the best practice on doing this with my above scenario in objective c.
I will post my code for the map below :
MapPin.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MapPin : NSObject <MKAnnotation>
{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
MapPin.m
#import "MapPin.h"
#implementation MapPin
#synthesize coordinate, title, subtitle;
#end
MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController
{
MKMapView *mapView;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
-(IBAction)SetMap:(id)sender;
-(IBAction)GetLocation:(id)sender;
-(IBAction)Directions:(id)sender;
#end
MapViewController.m
#import "MapViewController.h"
#import "MapPin.h"
#interface MapViewController ()<MKMapViewDelegate>
#end
#implementation MapViewController
#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];
mapView.delegate = self;
//new
//[self.mapView setShowsUserLocation:YES];
//Moss Preserve annotation and map pin
MapPin *MossPreserveAnnotation = [[MapPin alloc] init];
MossPreserveAnnotation.title = #"Moss Rock Preserve Boulder Fields";
MossPreserveAnnotation.subtitle = #"Hoover, AL";
MossPreserveAnnotation.coordinate = CLLocationCoordinate2DMake(33.3816566, -86.8415451);
[mapView addAnnotation:MossPreserveAnnotation];
//Setup map
MKCoordinateRegion mapCoordRegion;
mapCoordRegion.center.latitude = 39;
mapCoordRegion.center.longitude = -97;
mapCoordRegion.span.latitudeDelta = 60.0;
mapCoordRegion.span.longitudeDelta = 60.0;
[mapView setRegion:mapCoordRegion];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
self.navigationController.navigationBar.hidden = NO;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
// Create an MKMapItem to pass to the Maps app
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:view.annotation.coordinate
addressDictionary:nil];
MKMapItem *MapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[MapItem setName:view.annotation.title];
NSDictionary *launchOptions = #{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving};
// Get the "Current User Location" MKMapItem
MKMapItem *currentLocationItem = [MKMapItem mapItemForCurrentLocation];
[MKMapItem openMapsWithItems:#[currentLocationItem, MapItem]
launchOptions:launchOptions];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"MKPinAnnotationView"];
annotationView.canShowCallout = YES;
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[detailButton setTintColor:[UIColor colorWithRed:183/255.0 green:207/255.0 blue:85/255.0 alpha:0.5]];
annotationView.rightCalloutAccessoryView = detailButton;
return annotationView;
}
-(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;
}
}
-(IBAction)GetLocation:(id)sender;
{
mapView.showsUserLocation = YES;
}
-(IBAction)Directions:(id)sender;
{
NSString *urlString = #"http://maps.apple.com/maps?daddr=33.3816566,-86.8415451";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}
#end
Sorry to dump a lot of code in here... Just wanted to provide everyone with what I had.
Before answering, some notes:
Start methods in lower case, it's a common practice.
A pin and an annotation are two diferent concepts, let's say a pin is the view and an annotation is the model (or business object), so it's better if you call MapPin like MapAnnontation (or just Annontation, cause Map is redundant). Probably in a close future you are going to have custom pins, that are a subclass of MKAnnotationView.
For your reply, I have an app that retrieves places for the current map area from Parse (www.sharewifiapp.com). This is the code and below some explanations:
#pragma mark MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
[self.hotspotsQuery cancel];
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
//DDDebugLog(#"zoom %lu", (unsigned long)[self.mapView zoomLevel]);
// retrieve all hotspots using the filtering and the current view port
self.hotspotsQuery = [PFQuery queryWithClassName:[SWHotspot parseClassName]];
MKMapRect mRect = self.mapView.visibleMapRect;
MKMapPoint neMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), mRect.origin.y);
MKMapPoint swMapPoint = MKMapPointMake(mRect.origin.x, MKMapRectGetMaxY(mRect));
CLLocationCoordinate2D neCoord = MKCoordinateForMapPoint(neMapPoint);
CLLocationCoordinate2D swCoord = MKCoordinateForMapPoint(swMapPoint);
PFGeoPoint* swGeoPoint=[PFGeoPoint geoPointWithLatitude:swCoord.latitude longitude:swCoord.longitude];
PFGeoPoint* neGeoPoint=[PFGeoPoint geoPointWithLatitude:neCoord.latitude longitude:neCoord.longitude];
[self.hotspotsQuery whereKey:#"location" withinGeoBoxFromSouthwest:swGeoPoint toNortheast:neGeoPoint];
[self.hotspotsQuery includeKey:#"owner"];
[self.hotspotsQuery orderByDescending:#"updatedAt"];
self.hotspotsQuery.limit=1000;
self.loadingHotspotsActivityView.hidden=NO;
[self.hotspotsQuery findObjectsInBackgroundWithBlock:^(NSArray *hotspots, NSError *error) {
self.loadingHotspotsActivityView.hidden=YES;
if (error) {
DDLogError(#"Error retrieving hotspots: %#", [error userInfo][#"error"]);
} else {
// TEST.
/*
NSLog(#"retrieved: %lu", (unsigned long)objects.count);
[self.mapView removeAnnotations:self.mapView.annotations];
[self.mapView addAnnotations:objects];
*/
// remove hotspots that are not in the current response (hotstpots)
NSMutableArray* hotspotsToRemove=[self.mapView.annotations mutableCopy];
[hotspotsToRemove removeObjectsInArray:hotspots];
[self.mapView removeAnnotations:hotspotsToRemove];
// add hotpots from the current response that were not in the original set
NSMutableArray* hotspotsToAdd=[hotspots mutableCopy];
[hotspotsToAdd removeObjectsInArray:self.mapView.annotations];
[self.mapView addAnnotations:hotspotsToAdd];
}
}];
}
Important points:
-Save your parse query so you can cancel it.
-Cancel it when user starts moving the map, and launch a new request when user stops moving the map.
-Every time you receive new places from parse query, you can remove all annotations and put the new ones, but from a performance point of view that's not nice. If you want that try my code where it says TEST.
-If you want to improve performance, follow my logic, that removes annotations that are not in the current reply and only add new places if they are not in the map.
Hope this helps.
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;
//}
}
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.
I am trying to display user's current location on the map but for some reason, does not takes my default coordinates.
I have a MKMapView class that called inside a UIViewController.
MapView.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface MapView : MKMapView <MKMapViewDelegate, CLLocationManagerDelegate>{
CLLocationManager *locationManager;
}
#end
MapView.m
#import "MapView.h"
#interface MapView ()
#end
#implementation MapView
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
self.delegate = self;
[self addAnnotation:[self userLocation]];
[locationManager startUpdatingLocation];
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
NSLog(#"didUpdateUserLocation");
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 250, 250);
[self setRegion:[self regionThatFits:region] animated:YES];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"Where am I?";
point.subtitle = #"I'm here!!!";
[self addAnnotation:point];
}
- (MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
NSLog(#"viewForAnnotation");
static NSString *identifier = #"MyAnnotation";
if ([annotation isKindOfClass:[MKUserLocation class]]) {
NSLog(#"Is the user %f, %f", [annotation coordinate].latitude, [annotation coordinate].longitude);
return nil;
}
return nil;
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views{
NSLog(#"didAddAnnotationViews");
for (MKAnnotationView *view in views){
if ([[view annotation] isKindOfClass:[MKUserLocation class]]){
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([[view annotation] coordinate] , 250, 250);
[mapView setRegion:region animated:YES];
}
}
}
#end
I am getting the output below once access the map.
viewForAnnotation
Is the user 0.000000, 0.000000
didAddAnnotationViews
I can't understand why my didUpdateUserLocation: never get called even if re-submit custom coordinates.
What I am missing here?
You're using a CLLocationManager and setting it's delegate, but your delegate methods are all methods of MKMapViewDelegate.
You can either set the mapview's delegate, or use the locationManager:didUpdateLocations: CLLocationManagerDelegate method.
If it is important to you that the user have the option to turn his location on and off on the map then Nevan King is correct. However, if you are OK with continually showing the user location then no scripting is necessary. Simply click on your mapView in the Storyboard and on the right (in attributes, I think) check the "shows user location" box.