I try to get the direction from current location to other point using Google Map API. Everything is OK when i input the origin point and destination point manually. But, when i try to set the origin point as current location, the location is null as the following code:
mainMap=[[GMSMapView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithTarget:[mainMap.myLocation coordinate] zoom:13];
mainMap.camera=camera;
mainMap.myLocationEnabled=YES; // <---- The blue point appear on map: it's exactly my location
[self.view addSubview:mainMap];
//Get mylocation
CLLocation *myLocation = mainMap.myLocation; // <----- NULL
Is there any body know what is my problem here? Tks a lot
The thing is: Getting a location is asynchronous and how you do it is expect it to block till its there... which is not how it works
you have to add a KVO observer inn the map and observer myLocation.
Then when your observe method gets called, you get the myLocation.
(that's how the blue dot works too :))
- (void)viewDidLoad {
//...
[self.mapView addObserver:self forKeyPath:"myLocation" options:0 context:nil];
}
- (void)dealloc {
[_mapView removeObserver:self forKeyPath:#"myLocation"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([keyPath isEqualToString:#"myLocation"]) {
CLLocation *l = [object myLocation];
//...
}
}
Related
App is experiencing following crash and unable to understand the cause behind of this crash. This crash report I got it from App Store. This is the crash report screenshot
It is mostly affecting on iOS 10.2. In this class I'm using Google Maps, Pageviewcontroller and Timer. So, anyone can tell me how to figure out it?
This crash is happening due to fetching user current location from Google Maps by using addObserver forKeyPath:#"myLocation" options:NSKeyValueObservingOptionNew.
While dealloc Google Maps, that time you need to remove this Observer. Otherwise app will crash with following error
NSInternalInconsistencyException: An instance 0x1759f350 of class GMSMapView was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x0, Property: 0x177a4490> )
you need to addObserver before adding Google Maps to mapView like following:
// Listen to the myLocation property of GMSMapView.
[mapView_ addObserver:self
forKeyPath:#"myLocation"
options:NSKeyValueObservingOptionNew
context:NULL];
self.view = mapView_;
// Ask for My Location data after the map has already been added to the UI.
dispatch_async(dispatch_get_main_queue(), ^{
mapView_.myLocationEnabled = YES;
});
#pragma mark - KVO updates
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (!firstLocationUpdate_) {
// If the first location update has not yet been received, then jump to that
// location.
firstLocationUpdate_ = YES;
CLLocation *location = [change objectForKey:NSKeyValueChangeNewKey];
mapView_.camera = [GMSCameraPosition cameraWithTarget:location.coordinate
zoom:14];
}
}
then add this code also for removing the observer
- (void)dealloc {
[mapView_ removeObserver:self
forKeyPath:#"myLocation"
context:NULL];
}
for more details: Google Maps iOS SDK, Getting Current Location of user
I'm monitoring the center of a view with the key value observer pattern, as follows:
- (void)viewDidLoad {
[[self.balanceView viewWithTag:BASE_TAG] addObserver:self
forKeyPath:#"center"
options:0
context:BASE_CONTEXT];
}
I'm trying to retrieve the value of the centerpoint and output it to NSLog, as follows:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (BASE_CONTEXT == context) {
CGPoint baseCenter = [[change objectForKey:NSKeyValueChangeNewKey] CGPointValue];
NSLog(#"Base: (%f,%f)", baseCenter.x, baseCenter.y);
}
}
Whenever the UIView moves, an entry is output to NSLog. However, the centerpoint is always (0,0):
2014-07-18 20:48:51.210 Balance[8646:90b] Object: (0.000000,0.000000)
What is the correct way to retrieve the centerpoint?
options:0 gives you no change dictionary values -- if you want "new", you should use 1, or more appropriately, NSKeyValueObservingOptionNew.
I have an iOS app that uses Google Maps SDK to display a map within my app.
I have managed to get the map displaying but I dont know how to set the camera or the marker to the users current location.
I have hard coded the coordinates just to test is the map working but I am now stuck on how to display current location of the user.
Here is my code to centre the camera to a coordinate
- (void)viewDidLoad
{
[super viewDidLoad];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:47.995602 longitude:-78.902153 zoom:6];
self.mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
self.mapView.myLocationEnabled = YES;
self.mapView.mapType = kGMSTypeNormal;
self.mapView.accessibilityElementsHidden = NO;
self.mapView.settings.scrollGestures = YES;
self.mapView.settings.zoomGestures = YES;
self.mapView.settings.compassButton = YES;
self.mapView.settings.myLocationButton = YES;
self.mapView.delegate = self;
self.view = self.mapView;
[self placeMarkers];
}
And here is the code to display the marker at coordinates
-(void)placeMarkers
{
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(47.995602, -78.902153);
marker.title = #"PopUp HQ";
marker.snippet = #"Durham, NC";
marker.icon = [GMSMarker markerImageWithColor:[UIColor blueColor]];
marker.opacity = 0.9;
marker.map = self.mapView;
}
I have tried to get the current position as follows:
CLLocationCoordinate2D *myLocation = self.mapView.myLocation.coordinate;
but I get the error:
Initializing 'CLLocationCoordinate2D' with an expression of incompatible type 'CLLocationCoordinate2D'
How can I get the current location to pass to the camera as well as marker?
CLLocationCoordinate2D is just a struct containing a latitude and longitude, so you can simply use
CLLocationCoordinate2D myLocation = self.mapView.myLocation.coordinate;
It is also worth using KVO to observe changes to myLocation, as it is possible that the mapView won't yet have a valid location.
To explain further about KVO:
You can add an observer for the myLocation property as follows:
[self.mapView addObserver:self
forKeyPath:#"myLocation"
options:(NSKeyValueObservingOptionNew |
NSKeyValueObservingOptionOld)
context:NULL];
You should then implement the following method:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if ([keyPath isEqualToString:#"myLocation"]) {
// NSLog(#"My position changed");
}
}
You can then safely access self.mapView.myLocation.coordinate knowing that the location is valid.
Don't forget to remove yourself as an observer when the mapview is deallocated:
[self.mapView removeObserver:self forKeyPath:#"myLocation"];
As Saxon has already mentioned, the mapview will show it's own current position indicator. The marker that you are adding will be shown in addition, but it is likely that mapview doesn't yet having a valid position when you are creating the marker, so it is being added at latitude/longitude 0,0 which is in the middle of the ocean.
When you set myLocationEnabled to YES then the map automatically adds a marker at your current location. So you probably don't need to add your own?
It takes time for the device and your app to determine your location. When it starts up it probably doesn't know your location yet, so it defaults to lat/lon of zero, which is off Africa.
As NigelG said, you can use KVO on the myLocation property to find out when the position updates.
I have a GMSMapView properly loaded and working inside my viewcontroller
what i'm not being able to do is setting the GMSCameraPosition around my location
this is my code:
mapView_.myLocationEnabled = YES;
CLLocation* myLoc = [mapView_ myLocation];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:myLoc.coordinate.latitude
longitude:myLoc.coordinate.longitude
zoom:4];
[mapView_ setCamera:camera];
GPS is enabled and application has all needed permissions but myLocation returns a nil CLLocation, consequentially cameraWithLatitude:longitude:zoom: get 0 0 coordinates and displays Africa instead of my actual location (that is not in africa :) )
From official Google Maps iOS SDK documentation:
(BOOL) myLocationEnabled [read, write, assign]
Controls whether the My Location dot and accuracy circle is enabled.
Defaults to NO.
(CLLocation*) myLocation [read, assign]
If My Location is enabled, reveals where the user location dot is being drawn.
If it is disabled, or it is enabled but no location data is available, this will be nil. This property is observable using KVO.
So when you set mapView_.myLocationEnabled = YES;, it only tells the mapView to reveal the blue dot only if you have a location value given to the myLocation property. The sample code from Google shows how to observe the user location using the KVO method.(Recommended) You can also implement the CLLocationManagerDelegate method, to update the mapView.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[mapView animateToLocation:newLocation.coordinate];
// some code...
}
Here are the code from google maps sample code on how to use KVO to update user location.
// in viewDidLoad method...
// Listen to the myLocation property of GMSMapView.
[mapView_ addObserver:self
forKeyPath:#"myLocation"
options:NSKeyValueObservingOptionNew
context:NULL];
// Ask for My Location data after the map has already been added to the UI.
dispatch_async(dispatch_get_main_queue(), ^{
mapView_.myLocationEnabled = YES;
});
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (!firstLocationUpdate_) {
// If the first location update has not yet been recieved, then jump to that
// location.
firstLocationUpdate_ = YES;
CLLocation *location = [change objectForKey:NSKeyValueChangeNewKey];
mapView_.camera = [GMSCameraPosition cameraWithTarget:location.coordinate
zoom:14];
}
}
Try to using MapKit, under the VieDidLoad or ViewWillApper using:
myMapView.showsUserLocation = YES;
You can add this simple code under the IBAction if you want, like a :
- (IBAction)getLocation:(id)sender{
myMapView.showsUserLocation = YES;
}
I hope this help you
In my ios application i want to place a pin on map that will always show callout by default.on that callut i am showing lat,long of pin.
What i want is pin always remain in center of map.and when user move map pin do not get moved but its lat long get changed after moving map.
i also want to show address from that lat,long.
Please guide what are the ways.
i have tried this code to
[mMapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
MyAnnotation* obj = [[MyAnnotation alloc] initWithLocation:mMapView.centerCoordinate withPinType:StartPoint];
[obj setTitle:[NSString stringWithFormat:#"%f, %f",mMapView.centerCoordinate.latitude,mMapView.centerCoordinate.longitude]];
[mMapView selectAnnotation:obj animated:YES];
[mMapView addAnnotation:obj];
zoom map at current location
add pin on map center
showing lat long
Problem - when i move map.pin also get moved and lat long did not get changed
In your -viewDidLoad method add following code,
[mMapView.userLocation addObserver:self
forKeyPath:#"location"
options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld)
context:NULL];
Now include the following method,
// Listen to change in the userLocation
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
[object setTitle:[NSString stringWithFormat:#"%f, %f",mMapView.centerCoordinate.latitude,mMapView.centerCoordinate.longitude]];
[mMapView selectAnnotation:object animated:YES];
}
Please make sure your annotation object is class object.
Hope this will help...