I am integrating map feature into my application. I have displayed the current location. In my problem is, i am developing two applications and displayed the current location. But both the applications displayed the current location in different location and different view in the map. See my screenshots
Both the screenshots are taken by simulator with two applications and it shows the different Map view frame. But i have used the same code for that.(This happens in device also, show the different place with the map frame). I donno why the map view frame is changed? I have created the map view frame in XIB. And i have included the required frameworks and switched on the location services. Why the Map frame view change? It's weird to me.
Here my sample code is,
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
[mapview setShowsUserLocation:YES];
[locationManager startUpdatingLocation];
}
- (void)locationManager: (CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
MKCoordinateRegion region1;
region1.center = newLocation.coordinate;
//Change the Zoom level of the current location
//region1.span.latitudeDelta = 0.1;//0.0001
//region1.span.longitudeDelta = 0.1; //0.0001
mapview.mapType = MKMapTypeStandard;
//[mapview setRegion:region1 animated:TRUE];
[locationManager stopUpdatingLocation];
}
I hope, the first screen shot map view frame is correct. Because i have passed the map view co-ordinates(North East, North West, South East and South West) to the server. If the frame size is wrong, i will get the wrong user details from the server.
Please help me out.
Thanks!
The lines in your locationManager:didUpdateToLocation:fromLocation: that are commented out are required for the map view to be updated. You need the call to [mapView setRegion:animated] in order to change the view region. Is your code definitely the same in both applications?
I assume that you know that in the simulator the current location is always the Apple headquarters in Cupertino, as shown in your first screenshot.
Related
I'm developing an application that uses an iOS 6 MKMap view and I would like to enable the "user location button" (the one that you see at the bottom-left of the screen when you are using the Maps application).
I didn't find anything that could help me so I've tried to make this button myself with this code:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D currentCoordinates;
currentCoordinates.latitude = newLocation.coordinate.latitude;
currentCoordinates.longitude = newLocation.coordinate.longitude;
MKCoordinateRegion viewRegion = MKCoordinateRegionMake(currentCoordinates, _mapView.region.span);
[_mapView setRegion:viewRegion animated:YES];
[locationManager stopUpdatingLocation];
}
- (IBAction)moveToCurrentLocation:(id)sender {
[locationManager startUpdatingLocation];
}
So when I press the button the locationManager updates user's current location and the map changes it's region with a new one centered on user's current location and with the same span.
Now I have another problem: when I press the button the maps moves to the right coordinates but it also zooms out (in other words the span increases) even if I crete a new region with the old span.
I can't understand this behavior, I would like to preserve the old span as the Map app does.
That button on maps is toggling the userTrackingMode property on the mapView, so set it to one of these:
MKUserTrackingModeNone //nothing, normal map view
MKUserTrackingModeFollow //user is highlighted and stays centered on map when you move
MKUserTrackingModeFollowWithHeading //you get the heading as well, so your direction is up on the map
If you want to use the official iOS button for that, this code will add it to your UIToolbar and connect it to your mapview
UIBarButtonItem *trackingButton = [[MKUserTrackingBarButtonItem alloc] initWithMapView:self.mapView];
NSMutableArray *items = [[NSMutableArray alloc] initWithArray:self.toolbar.items];
[items addObject:trackingButton];
[self.toolbar setItems:items];
I set up cllocation manage by following code. It work in the open area. However, my phone can't received any datas (all datas was 0) after I went into subway or underground area.
What should I do if I want to make app work in subway as well? Is it necessary to integrate startMonitoringSignificantLocationChanges/startMonitoringForRegion method with standard location update method together? If so, how do I make it?
In init method
locationManager=[[CLLocationManager alloc]init];
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
locationManager.distanceFilter=kCLDistanceFilterNone;
locationManager.delegate=self;
[locationManager startUpdatingLocation];
In cllocation delegate method
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(#"%#",newLocation);
NSDate*eventDate=newLocation.timestamp;
NSTimeInterval howRecent=abs([eventDate timeIntervalSinceNow]);
if ((newLocation.coordinate.latitude != oldLocation.coordinate.latitude)&&(newLocation.coordinate.longitude != oldLocation.coordinate.longitude)) {
locationChanged=YES;
}else{
locationChanged=NO;
}
if ((howRecent <5.0)&&
((newLocation.horizontalAccuracy<(oldLocation.horizontalAccuracy -10.0))||
(newLocation.horizontalAccuracy<50.0)||
((newLocation.horizontalAccuracy<=120)&& locationChanged))) {
self.myLocation=[newLocation copy];
// NSLog(#"mylocation==%#",[self.myLocation description]);
}
//location info draw from plist
CLLocation *targetLocation = [[CLLocation alloc] initWithLatitude:Target_LAT longitude:Target_LONG];
double distance = [self.myLocation distanceFromLocation:targetLocation]/1000;
NSString*distString=[NSString stringWithFormat:#"%0.2f km",distance];
[delegate getLocationUpdate:self.myLocation distanceUpdate:distString];
//In this testing app, I use delegate to take cllocation data. Then those datas display in view controller.
}
You can get location data for a mobile device In a Couple of ways. Device based (GPS, AGPS, WIFI etc when you are in GPS line of sight ) or CELLID based (off device - mobile number based whether you are in GPS line of sight or not as this is cellID based)..as you know your app can also get location information underground(out of line of sight) if it is using cellID Keep in mind that in underground situations if there is no wifi then you are out of luck.
I would love to say that you should use geoloqal.com (me) to locate mobile devices via cellID or GPS - however, unfortunately, in the subway we still will not be able to help you.
How do we follow the user in maps. I want to have the blue dot (user location) be in the center of the map, But I also what to allow the user to zoom in and zoom out and then after a couple seconds zoom in back in the user location.
My Educated Guess for the Solution: We detect if the user is zooming in or out, after three seconds of no zooming in or out detection, we starting follow the user :). Your HELP would be awesome :)
This code zoom in the user location but doesn't delay for zoom in and out:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
MKCoordinateRegion userLocation = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 1500.0, 1500.0); [mapView setRegion:userLocation animated:YES];
}
A quick look in the docs reveals the magic.
Set the userTrackingMode of your map to MKUserTrackingModeFollow.
See here.
Update:
Since you've updated your question, here's the new answer.
To recenter the map to the user location i would recommend to write a simple helper Method:
- (void)recenterUserLocation:(BOOL)animated{
MKCoordinateSpan zoomedSpan = MKCoordinateSpanMake(1000, 1000);
MKCoordinateRegion userRegion = MKCoordinateRegionMake(self.mapView.userLocation.coordinate, zoomedSpan);
[self.mapView setRegion:userRegion animated:animated];
}
And now you should call it after a short delay if user has stopped moving the map. You can do this in the regionDidChange delegate method of the mapView.
But you can get problems if you don't lock the reset-method if the user changes the region multiple times before it really resets the map. So it would be wise to make a flag if it is possible to recenter the map. Like a property BOOL canRecenter.
Init it with YES and update the recenterUserLocation method to:
- (void)recenterUserLocation:(BOOL)animated{
MKCoordinateSpan zoomedSpan = MKCoordinateSpanMake(1000, 1000);
MKCoordinateRegion userRegion = MKCoordinateRegionMake(self.mapView.userLocation.coordinate, zoomedSpan);
[self.mapView setRegion:userRegion animated:animated];
self.canRecenter = YES;
}
Now you can call it safely after the user has moved the map in any way with a small delay:
- (void)mapView:(MKMapView *)mMapView regionDidChangeAnimated:(BOOL)animated{
if (self.canRecenter){
self.canRecenter = NO;
[self performSelector:#selector(recenterUserLocation:) withObject:#(animated) afterDelay:3];
}
}
I had the same problem. I guessed:
If the user drag the map, he wants to stay on that position.
If the user do nothing or reset to show current location, I need to follow the user.
I added a reset button to show the current user location like this:
On the reset button clicked, changed the needToCenterMap to TRUE
Added a drag gesture recognizer on map
// Map drag handler
UIPanGestureRecognizer* panRec = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(didDragMap:)];
- (void)didDragMap:(UIGestureRecognizer*)gestureRecognizer {
if (gestureRecognizer.state == UIGestureRecognizerStateEnded){
NSLog(#"Map drag ended");
self.needToCenterMap = FALSE;
}
}
Followed the user on map depending on needToCenterMap flag
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
if (self.needToCenterMap == TRUE)
[mapView setCenterCoordinate:userLocation.location.coordinate animated:YES];
}
I made a little example to show how you can delegate this job to the Map SDK.
Of course you could listen to the Location change but MKUserTrackingModeFollow automatically does this for you, so just a single line of code
#import <MapKit/MapKit.h>
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
MKMapView *mapView = [[MKMapView alloc] initWithFrame:self.view.frame];
//Always center the dot and zoom in to an apropriate zoom level when position changes
[mapView setUserTrackingMode:MKUserTrackingModeFollow];
//don't let the user drag around the the map -> just zooming enabled
[mapView setScrollEnabled:NO];
[self.view addSubview:mapView];
}
Then the app looks like this:
For more information just read the Apple Documentation:
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html
This shell do the trick: mkMapview.showsUserLocation = YES;
I cannot get my current location in iphone simulator. I set custom location to latitude and longitude to Egypt but doesn't get current location.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Make this controller the delegate for the map view.
self.MapView.delegate = self;
// Ensure that you can view your own location in the map view.
[self.MapView setShowsUserLocation:YES];
//Instantiate a location object.
locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
//Make this controller the delegate for the location manager.
[locationManager setDelegate:self];
//Set some parameters for the location object.
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
and this is delegate :
#pragma mark - MKMapViewDelegate methods.
- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
{
MKCoordinateRegion region;
region = MKCoordinateRegionMakeWithDistance(locationManager.location.coordinate,2000,2000);
[mv setRegion:region animated:YES];
}
Please any one help me.
What's the problem exactly? Not getting a userLocation where you're supposed to have or not moving the map region to the right place?
If it's the first, it is mostly a tools issue, not a code issue:
If your location is in a gpx file inside your project you should be able to start at it by editing Scheme / Options / Allow Location Simulation / and choose your default Location
And you should have a DemoStart.gpx file in your project that looks like:
<?xml version="1.0"?>
<gpx version="1.1" creator="Xcode">
<wpt lat="20.88072" lon="10.67429">
<name>Demo Starting Location</name>
</wpt>
</gpx>
(Sorry, I'm too lazy to find Egypt's exact coordinates).
You must first be sure your CLLocationManager updates his location to yours. To do that, set the view controller as the CLLocationManager's delegate, you already did so, and save this location. Try calling startUpdatingLocation after you finished doing all the setup and also set showsUserLocation to YES.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// If it's a relatively recent event, turn off updates to save power
CLLocation* myLocation = [locations lastObject];
}
Be sure you are testing this on iOS Simulator Version >= 5.1
I have a simple mapview that has the following viewdidload method and didupdate to location:
- (void)viewDidLoad {
NSLog(#"in view did load");
[super viewDidLoad];
self.mapView.showsUserLocation = YES;
self.put_url = nil;
locationManager = [[CLLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager setDelegate:self];
noUpdates = 0;
[locationManager startUpdatingLocation];
self.availableParking = [[NSMutableArray alloc] init];
//self.availableParking = nil;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(#"in didupdatetolocatoin");
if([newLocation horizontalAccuracy] < 100 && [newLocation horizontalAccuracy] > 0) {
// Add annotation to map
DDAnnotation *annotation = [[DDAnnotation alloc] initWithCoordinate:newLocation.coordinate title:#"Park Here?"];
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.05;
region.span = span;
region.center = newLocation.coordinate;
self.mapView.region = region;
NSLog(#"in didupdatetolocation");
noUpdates++;
NSLog(#"IN UPDATELOCATION NOUPDATES = %d",noUpdates);
if (noUpdates == 1) {
[self.mapView addAnnotation:annotation];
NSLog(#"ADDED ANNOTATION IN didUpdateToLocation!!");
[locationManager stopUpdatingLocation];
[self.settingsViewController setState:self.mapView.userLocation.subtitle andCity:#"fuckface"];
NSLog(#"STOPPED UPDATING LOCATION");
UpdateLocation *updatedLocation = [[[UpdateLocation alloc] initWithUserid:#"fuckface" andCoordinate:newLocation.coordinate withMapViewController:self]
autorelease];
NSLog(#"Lat = %f, Long = %f",newLocation.coordinate.latitude,newLocation.coordinate.longitude);
//[NSThread detachNewThreadSelector:#selector(getLocations) toTarget:self withObject:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(sendUpdate)
name:#"NoteFromOne"
object:updatedLocation];
}
// We only update location once, and let users to do the rest of the changes by dragging annotation to place they want
} else {
NSLog(#"Accuracy not good enough %lf", [newLocation horizontalAccuracy]);
}
}
When Im connected to a wireless network it works flawlessly zooming in and dropping an annotation pin in my current location. Over the 3G network it never zooms or drops the pin. Any ideas as to why? Thanks in advance.
Here's a couple of screen shots:
With 3G:
alt text http://www.freeimagehosting.net/uploads/fe7fcbb2ea.jpg
With wifi:
alt text http://www.freeimagehosting.net/uploads/6b653e60a7.jpg
The GPS unit has nothing to do with the network connection (unless the GPS signal is not available, in which case the GPS may try to use the wifi hotspot or the cell your device is connected to in order to infer your location). It works independently of it if the GPS signal is available, and the network is only used to actually show the map. From the code snipped you posted, you only show the map when you reach an horizontal accuracy less than 100 meters, otherwise you let the GPS unit updating the location. However, if you try your code in the exact SAME place, the GPS unit on your device should always return the same updates. Therefore, I really do not understand the behaviour you are describing: this would be possible only if the GPS unit returned different updates for the same place when a different network connection is available because the GPS signal is not available. Are you seeing the same latitude/longitude in the two cases or not? Are you seeing the same accuracy? Be careful to measure this in exactly the same place in both cases.
If you obtain the same updates, then it may be possible that your 3G cellular connection is simply not powerful enough or is only apparently available, so that you did not get the map. Try testing the speed of your 3G network from the same place.
A related consideration. You should allow the GPS unit to work until either a specified amount of time elapses (say 20 seconds, use NSTimer for this) or until you reach a specified level of accuracy, whichever happens first. Otherwise you may end up consuming too much the battery.