it is my first time to use google map and i asked to let the user choose the location that he wanted to point by taping on the map. when the application start it will point on the device location how the user will change it to the location he wants?
First get the point of user's tap. Then, get coordinate value for that CGPoint and set it as mapView's center.
-(void)handlePan:(UIPanGestureRecognizer *)recognizer
{
// Get tap point
CGPoint tapPoint = [recognizer locationInView:[recognizer superView]];
// Convert CGPoint to CLLocationCoordinate2D
CLLocationCoordinate2D center = [self.mapView.projection coordinateForPoint:tapPoint];
// Set camera of mapView
GMSCameraPosition * camera = [GMSCameraPosition cameraWithLatitude:center.latitude longitude:center.longitude zoom:self.mapView.camera.zoom];
[self.mapView setCamera:camera];
}
Alternatively you can implement the GMSMapViewDelegate and use the - mapView:didTapAtCoordinate: method.
You can move the view port by doing something similar like this to move the center point of map view
GMSCameraPosition *sydney = [GMSCameraPosition cameraWithLatitude:-33.8683
longitude:151.2086
zoom:6];
[mapView_ setCamera:sydney];
(Google Map SDK called it camera position, as if you use a camera to target a portion of the whole map)
Checkout https://developers.google.com/maps/documentation/ios/views?hl=en Moving the camera section
So here, in order to finish your task with move use to the point where he tapped. You'll need to do following steps:
define a iVar or property to keep record of the tap point location(lat/lng):
CLLocationCoordinate2D *currentTapLocation;
In didTapAtCoordinate delegate, fetch that position
- (void) mapView:(GMSMapView *) mapView didTapAtCoordinate:(CLLocationCoordinate2D) coordinate{
currentTapLocation = coordinate;
}
Create a GMSCamera and set camera to currentTapLocation
- (void) mapView:(GMSMapView *) mapView didTapAtCoordinate:(CLLocationCoordinate2D) coordinate{
currentTapLocation = coordinate;
GMSCameraPosition *newCameraPosition = [GMSCameraPosition cameraWithLatitude:currentTapLocation.latitude
longitude:currentTapLocation.longitude
zoom:6];
[mapView_ setCamera:newCameraPosition];
}
Optional step: if you want animate to the new position instead setCamera directly,
you can do:
[mapView_ animateWithCameraUpdate:[mapView_
setCamera:newCameraPosition];];
instead of
[mapView_ setCamera:newCameraPosition];
Related
I have an MKMapView that has a MKTileOverlay so that I can show Open Street Map tiles:
NSString *templateURL = #"http://tile.openstreetmap.org/{z}/{x}/{y}.png";
self.tileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:templateURL];
self.tileOverlay.canReplaceMapContent = YES;
[self.mapView addOverlay:self.tileOverlay level:MKOverlayLevelAboveLabels];
I also want to show an MKPolyline from my current location to Apple Park in Cupertino. This polyline needs to be updated as I move, and since an MKPolyline object isn't mutable, I have to remove it and add it for each location update:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray*)locations {
self.currentLocation = userLocation;
// Update polyline
CLLocationCoordinate2D applePark = CLLocationCoordinate2DMake(37.334626, -122.008895);
[self buildPolylineWithDestinationLocation:applePark];
}
- (void)buildPolylineWithDestinationLocation:(CLLocationCoordinate2D)coordinate {
// Remove the polyline each time so we can redraw it
if (self.polylineApple) {
[self.mapView removeOverlay:self.polylineApple];
}
// Get current location
CLLocation *location = self.currentLocation;
CLLocationCoordinate2D currentLocation = location.coordinate;
CLLocationCoordinate2D points[2];
points[0] = currentLocation;
points[1] = coordinate;
// Remove all route polylines
MKPolyline *oldPolyline = self.polylineApple;
// Draw a line
self.polylineApple = [MKPolyline polylineWithCoordinates:points count:2];
[self.mapView addOverlay:self.polylineApple];
if (oldPolyline) {
[self.mapView removeOverlay:oldPolyline];
oldPolyline = nil;
}
}
The problem is, this used to work great in older versions of iOS, but ever since iOS 13 this has caused the tiles to be redrawn each time that MKPolyline is removed and added:
Is this just an iOS 13 bug, or is there something I need to fix in my code to make this not happen?
As I know since iOS 8, I have seen this issue. Not always but some times.
This issue is linked to 2 things:
1) The action every second to remove and add again a polyline will ask the MKMapView to redrawn the part with the polyline and as a consequence the MKTileOverlay below.
2) If the tile's size (in KB, not the resolution) is low, the issue may not be present.
The best advice I can give to you is to add you own view to the MKMapView and update this own view by calling setNeedsDisplay. It will trigger the draw method where you can convert the map points (latitude, longitude) to screen points and draw the line.
Edit: A link speaking about MKTileOverlay reload issue
https://forums.developer.apple.com/message/313677#313677
I am trying to position my custom marker in iOS(Objective-C) with Google Maps.
Map view is all showing up fine with marker, however, moving the map will take the marker with it as its fetching current location. What I am looking for is the have it set to center of the map container, which will then fetch coordinates of map pin and display in search bar.
I am thinking I am doing this in reverse? I added the customer marker as a UIImage of the map container however it still does not show. Should I be getting the location from the position of the map marker, and then reverse geocoding address from there.
- (void)addPins:(float)lat andLng:(float)lng andName:(NSString*)strName withAddress:(NSString*)strAddr
{
// Creates a marker in the center of the map.
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(currentUserLocation.coordinate.latitude, currentUserLocation.coordinate.longitude);
NSLog(#"lat : %f, lng : %f", lat, lng);
marker.icon = [UIImage imageNamed:#"map_pin"];
marker.title = strName;
marker.snippet = strAddr;
marker.appearAnimation = kGMSMarkerAnimationPop;
marker.map = mapView;
}
The user needs to be able to search and set their address, besides their current location.
Thanks
Use your mapView delegate and use the responder to re-center your pin and re-fire your geocoordinate lookup.
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
Edit: If GMS Maps does not have these delegates, the approach may work with using whatever [mapView didUpdate]callback they have documented.
You can set GMSCameraPosition for centering your marker
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:"YOUR LATITUDE"
longitude:"YOUR LONGITUDE"
zoom:centerZoom];
"YOUT GMSMAPVIEW" = [GMSMapView mapWithFrame:"YOUR VIEW".bounds camera:camera];
Am actually dealing with the Google Maps Framework for iOS, and I want to block scrolling out side a giving area.
What I tried to do at first, implement the delegate method : - (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position and compare the map position with the right/left corners.But what I did has many issues when scrolling or zooming.
Below an exemple of my implementation :
- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {
if (position.target.latitude > topLat) {
GMSCameraPosition *goBackCamera = [GMSCameraPosition cameraWithLatitude:topLat
longitude:position.target.longitude
zoom:position.zoom
bearing:220
viewingAngle:0];
[self.mapView animateToCameraPosition:goBackCamera];
}
if (position.target.latitude < bottomLat) {
GMSCameraPosition *goBackCamera = [GMSCameraPosition cameraWithLatitude:bottomLat
longitude:position.target.longitude
zoom:position.zoom
bearing:220
viewingAngle:0];
[self.mapView animateToCameraPosition:goBackCamera];
}
if (position.target.longitude > rightLong) {
GMSCameraPosition *goBackCamera = [GMSCameraPosition cameraWithLatitude:position.target.latitude
longitude:rightLong
zoom:position.zoom
bearing:220
viewingAngle:0];
[self.mapView animateToCameraPosition:goBackCamera];
}
if (position.target.longitude < leftLong) {
GMSCameraPosition *goBackCamera = [GMSCameraPosition cameraWithLatitude:position.target.latitude
longitude:leftLong
zoom:position.zoom
bearing:220
viewingAngle:0];
[self.mapView animateToCameraPosition:goBackCamera];
}
}
Do you no a way more efficient to deal with this?
PS: TopLat, RightLong ... mean top Latitude and Right longitude etc
Regards
One way I can think of is by setting up the bound in the map in you want maps to scroll using GMSCoordinateBounds.
Next thing you can do is to set up the scroll gesture to true just within that section of maps you have specified above bounds. For the rest of the map the scroll gesture should be false.
Use GMSCoordinateBounds(northeast co-ordinates, southwest co-ordinates) method.
This might be helpful
GMSCoordinateBounds Class Reference
I am working with a GMSMapView that I have added as a custom UITableViewCell. When I first create the map and capture an initial user tap, my coordinates are based as though the user tapped near lat/lon 0/0 -- I get values like -1.800144/-1.867676 even though my map center is set to 43.50 and -116.22 (and the map displays around those coordinates).
However, when I move the map by panning it once, and then tapping on it, my coordinates are more along the line of what I expect. Also, if I add the following code to the GMSMapViewDelegate method mapView:idleAtCameraPosition: I get the correct coordinates the first time:
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
GMSCameraUpdate *update = [GMSCameraUpdate setCamera:position] ;
[mapView moveCamera:update] ;
}) ;
But that seems like a hack that is hiding a more fundamental issue.
Here is the relevant code:
My custom table view cell creates the initial mapView in its constructor:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Camera position is moot, just need something to instantiate the map view
GMSCameraPosition * cameraPosition = [GMSCameraPosition cameraWithLatitude:0 longitude:0 zoom:5];
GMSMapView * mapView = [GMSMapView mapWithFrame:CGRectZero camera:cameraPosition];
_mapView = mapView ;
}
return self;
}
In my view controller, I set the gestures enabled, set my delegate and my map bounds:
- (void) configureMap
{
[_mapView.settings setAllGesturesEnabled:YES];
[_mapView.settings setConsumesGesturesInView:YES] ;
_mapView.delegate = self ;
// _userTrip has among other things, a bounds for our map
GMSCoordinateBounds * bounds = _userTrip.bounds ;
DDLogInfo(#"Trip Bounds are sw(%f:%f) ne(%f:%f)", bounds.southWest.latitude, bounds.southWest.longitude, bounds.northEast.latitude, bounds.northEast.longitude) ;
GMSCameraUpdate *cameraUpdate = [GMSCameraUpdate fitBounds:bounds];
[_mapView moveCamera:cameraUpdate];
}
My delegate for camera position:
- (void) mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position
{
DDLogInfo(#"User changed map size. Zoom is now set to %f", mapView.camera.zoom) ;
/* putting this in 'fixes' the problem
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
GMSCameraUpdate *update = [GMSCameraUpdate setCamera:position] ;
[mapView moveCamera:update] ;
}) ;
*/
}
My delegate method for taps:
- (void) mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate
{
DDLogInfo(#"User did tap at coordinate %f, %f", coordinate.latitude, coordinate.longitude) ;
DDLogInfo(#"Map view center %f %f and zoom is %f", mapView.camera.target.latitude, mapView.camera.target.longitude, mapView.camera.zoom) ;
}
Sample output:
[] Trip Bounds are sw(43.409890:-116.435511) ne(43.597180:-116.023860)
[] map view zoom = 10.053131
[] User changed map size. Zoom is now set to 10.053131
--- At this point, the map is displayed and it shows the right location based on the bounds in the log statement above. Then, when I tap on the map:
[] User did tap at coordinate -0.262352, -0.900879
[] Map view center 43.503608 -116.229685 and zoom is 10.053131
--- As you can see above, the user coordinates are way off based on where the map thinks it is. Below, I have panned the map and then did another tap
[] User changed map size. Zoom is now set to 10.053131
[] User did tap at coordinate 43.447926, -116.340871
[] Map view center 43.426753 -116.377271 and zoom is 10.053131
As you can see, the user coordinates now appear to be a valid location on the map. I have verified through the debugger that the same map instance is being referenced throughout and it has the same gestureRecognizer.
I had a previous version of the same code that did not put the GMSMapView inside a table view cell, and it does not exhibit the same problem. So, I suspect there is an initialization issue caused by putting this in a UITableViewCell.
Anyone run across something like this and have any idea how to fix it?
In my application there is an MKMapView and I am trying to get the center coordinates of the map region that is currently visible. I am using following method so that if user moves the visible region I'll get new center coordinates.
- (void)mapView:(MKMapView *)mapView1 regionDidChangeAnimated:(BOOL)animated
{
CLLocationCoordinate2D centre = [mapView centerCoordinate];
NSLog(#"MAP CENTER = %f,%f",centre.latitude,centre.longitude);
}
the problem is that when I switch to the UIViewController that contains MKMapView it gives MAP CENTER = 0.000000,0.000000 for two times then gives the actual coordinates MAP CENTER = 55.755786,37.617633. I want the actual coordinates as soon as I switch to that UIViewController.
Is the coordinates (55.755786,37.617633) your current location ?
MKMapView takes some time to get a lock on GPS to fetch the coordinates for your current location. Until then centerCoordinate might return (0,0)
Try this this may help you.
self.mapView.centerCoordinate = self.mapView.userLocation.location.coordinate;