Is there any alternative to get User location and do GeoFence rather than using Location Services in iOS. I am asking this because, when we enable Location Services, battery consumption is too high. That's why I am looking for an alternative. What can I try?
If you are using map then, no need to implement location service code to capture current location, set YES to showUserLocation property of MKMapView
[self.mapView setShowsUserLocation:YES]; and implement its delegate method:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
`
[self.mapView setShowsUserLocation:YES];
[self.mapView setDelegate:self];
[self.mapView setMapType:MKMapTypeStandard];
[self.view addSubview:self.mapView];
[self.view bringSubviewToFront:self.viewLiveDrive];`
delegate :
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
NSLog(#"Location Current : %# ",userLocation.location);
[self.mapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
}
Now you can enjoy with current location :)
Related
I am using am mapview and sometimes my map will zoom onto my users location when I open it but sometimes it will zoom to the middle of an ocean. I don't know what is causing this, this is the code I am using for zooming. I don't want the map to track the user but just zoom to their location once they open the map
-(void) viewDidAppear:(BOOL)animated{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.mapView.userLocation.coordinate, 600.0f, 600.0f);
[self.mapView setRegion:region animated:YES];
}
-(void) viewDidLoad{
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
}
I encountered this issue before. It seems that mapView is slow to load and detect user location sometimes, resulting in your code in viewDidAppear being executed before the map view can check user's location. Thus, the spot in the ocean.
It will be better to use mapView's delegate to display user location when it's ready:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
if(isShowUserLocation)
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 600.0, 600.0);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
isShowUserLocation = NO;
}
}
Set isShowUserLocation = YES in viewDidLoad. This ensures the user location is shown once on entry and also selectively when you need it.
Edit 1:
#implementation MapViewController
{
BOOL isShowUserLocation;
}
-(void) viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
isShowUserLocation = YES;
}
Edit 2:
Alternatively, use CLLocationManager - see this post. It allows you stop the updating. Do include CoreLocation.framework. You may need to handle some nitty-gritty issues when interacting CLLocationManager with MapView though.
When you pass 0's for lat and long, you will git a spot in the middle of the ocean south of Ghana in Africa.
I have an MKMapView but when the user logs on the first time and allows location services, it doesn't show there location. If they leave the view and come back, it works. I am using what is listed bellow to solve the problem. It solves the problem but then the user can no longer zoom because when there location is updated, it takes them back to the specified location. How would I fix the first problem while making scrolling work.
Here is what I am using:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
MKUserLocation *myLocation = [self.schoolMap userLocation];
CLLocationCoordinate2D coord = [[myLocation location] coordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coord, 9000, 9000);
[self.schoolMap setRegion:region animated:NO];
}
Do not use location manager at all. Just tell the map view to track the user's location. Then implement this delegate method:
- (void)mapView:(MKMapView *)mapView
didUpdateUserLocation:(MKUserLocation *)userLocation {
CLLocationCoordinate2D coordinate = userLocation.location.coordinate;
MKCoordinateRegion reg =
MKCoordinateRegionMakeWithDistance(coordinate, 600, 600);
mapView.region = reg;
}
Now, that will keep trying to set the map every time the user moves, so if you don't want that, add a BOOL switch so that you only do this the first time (when the map first gets the user location).
It is possible that you did not received user's location by the time you set the region. There's a way to handle this situation by letting the mapView shows the user's location whenever it got to as follows:
CLLocation *location = [[self.schoolMap userLocation] location];
bool hasLocation = location!=nil;
if (!hasLocation) {
[self.mapView showsUserLocation];
} else {
CLLocationCoordinate2D zoomLocation = location.coordinate;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 2000, 2000);
[self.mapView setRegion:viewRegion animated:NO];
Note that this does not demand you update the location on a regular basis.
Using latitude and longitude I want to display the correct position by annotation. My app is showing the area, but not the correct position by annotation.
Here is my code:
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.mapView.delegate=self;
[self.mapView setShowsUserLocation:YES];
locatinmanager=[[CLLocationManager alloc]init];
[locatinmanager setDelegate:self];
[locatinmanager setDistanceFilter:kCLDistanceFilterNone];
[locatinmanager setDesiredAccuracy:kCLLocationAccuracyBest];
}
#pragma mark - MKMapViewDelegate methods.
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKCoordinateRegion region;
region.center.latitude=13.0839;
region.center.longitude=80.2700;
[mapView setRegion:region animated:YES];
}
You have set the region for your map but not the annotation.
For blue dot you need to add annotation for the same latitude and logitude.
Add following code with yours.
MapPoint *mp = [[MapPoint alloc] initWithCoordinate:**YouReagionsCordinat** title:#"**yourLocation**"];
[mapView addAnnotation:mp];
If still you are stucking then go through This tutorial
.
I have an MKMapView as part of a Navigation Controller in a Tab Bar based app.
I click a UIButton on the first View Controller and it pushes to the second View Controller which contains the MKMapView. When the Map View loads, it zooms in on the user's location using:
- (void)mapView:(MKMapView *)theMapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
if ( !initialLocation )
{
self.initialLocation = userLocation.location;
MKCoordinateRegion region;
region.center = theMapView.userLocation.coordinate;
region.span = MKCoordinateSpanMake(2.0, 2.0);
region = [theMapView regionThatFits:region];
[theMapView setRegion:region animated:YES];
}
}
When I hit the back button on the Navigation Controller above the MapView and then click back to the map, it no longer zooms in on the user's current location, but just has the full zoom out default:
Here's a picture of the view the second time.
I figure it would work correctly if I could somehow call the didUpdateUserLocation in the viewDidAppear method but I'm not sure how to pull this off since the didUpdateUserLocation is a delegate method.
Is that the right approach or is there a different approach I should take to do this? Thanks!
P.S. I've seen this question but it's slightly different with it's use of a modal view controller
I would pull all of the zooming code into its own method that can be messaged from -viewDidAppear: and -mapView:didUpdateToUserLocation:.
- (void)zoomToUserLocation:(MKUserLocation *)userLocation
{
if (!userLocation)
return;
MKCoordinateRegion region;
region.center = userLocation.location.coordinate;
region.span = MKCoordinateSpanMake(2.0, 2.0); //Zoom distance
region = [self.mapView regionThatFits:region];
[self.mapView setRegion:region animated:YES];
}
Then in -viewDidAppear:...
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self zoomToUserLocation:self.mapView.userLocation];
}
And in the -mapView:didUpdateToUserLocation: delegate method...
- (void)mapView:(MKMapView *)theMapView didUpdateToUserLocation:(MKUserLocation *)location
{
[self zoomToUserLocation:location];
}
I need some help with an app i'm making using MapKit
I'm struggling with the didUpdateUserLocation: - it keeps randomly crashing the app. When I comment out all of the code it works perfectly but this isn't a suitable situation. I've been fiddling around with it all but still no real success.
Here's my code
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
NSLog(#"update loc");
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 250.0, 250.0);//MKCoordinateRegionMake(userLocation.coordinate, mapView.region.span);
if (first) {
region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 250.0, 250.0);
first = false;
}
if (!CLLocationCoordinate2DIsValid(userLocation.coordinate)) {
//do nothing, invalid regions
NSLog(#"co-ord fail");
} else if (region.span.latitudeDelta <= 0.0 || region.span.longitudeDelta <= 0.0) {
NSLog(#"invalid reg");
} else {
[mapView setRegion:region animated:NO];
}
}
The app never hits "co-ord fail" or "invalid reg" so I don't really know what the problem is since I set the values myself.
The problem usually occurs when the nib for the Map is closed and it has dealloced the view.
I have seen some other suggestions but haven't been confident about their work. Ideally I'd like to use mapView.region.span so to maintain the zoom levels
Many Thanks,
James
Watch out that if an App that was suspended a short while, on resume the
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
delegate receives as the first userLocation (0.0,0.0) as latitude,longitude! I think that is a bug.. Check:
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
NSLog( #"userLocation:(%p) %#",userLocation,userLocation);
NSLog( #"userLocation.location:(%p) %#",userLocation.location,userLocation.location);
NSLog( #"userLocation.coordinate: %f,%f valid:%d",userLocation.coordinate.latitude,userLocation.coordinate.longitude, CLLocationCoordinate2DIsValid(userLocation.coordinate));
NSLog( #"userLocation.location.coordinate: %f,%f valid: %d",userLocation.location.coordinate.latitude,userLocation.location.coordinate.longitude, CLLocationCoordinate2DIsValid(userLocation.location.coordinate));
Result:
userLocation:(0x193fc0) <MKUserLocation: 0x193fc0>
userLocation.location:(0x0) (null)
userLocation.coordinate: -180.000000,-180.000000 valid:0
userLocation.location.coordinate: 0.000000,0.000000 valid: 1
Odd that 0,0 is produced from userLocation.location.coordinate while userLocation.location is nil, resulting in a valid coordinate, even!
Indeed the check on userLocation.location being nil seems best.
The problem usually occurs when the nib for the Map is closed and it
has dealloced the view.
[mapView setRegion:region animated:NO];
Well isn't that your problem then?
This is why we have dependency inversion patterns like Observer/Listener.
Instead of fiddling around with the view directly with your CLLocationManager delegate, use NSNotification to alert subscribing views (such as your MapView) that it should update. If the MapView has been dealloced it won't do anything.