I am building an iOS app in swift that use the google maps.
The app show the POI near the user, and when I move the map I refresh the POI using a refresh button
#IBAction func refreshPlaces(sender: AnyObject) {
fetchNearbyPlaces(mapView.camera.target)
}
Can I can refresh the POI when I move the map?
Make sure that you declare that your view controller conforms to the GMSMapViewDelegate and that you set self.mapView.delegate = self in that view controller (usually in viewDidLoad).
Then add the rolling method in your view controller:
func mapView(mapView: GMSMapView!, didChangeCameraPosition position: GMSCameraPosition!) {
fetchNearbyPlaces(position.target)
}
Related
I want to check and detect when tap on map marker or anything. Do any delegates exist for this case with google maps in iOS Swift 4?
Thanks.
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
//Write your code here...
}
if the delegate function is not called then set the mapview delegate in viewDidAppear() method or in LocationManager didUpdateLocations() method.
I'm trying to figure out how to add a Long press gesture to a map annotation(Mapbox).I have my code set up so that when a user tap's the annotation they segue to another view by putting my code in this function.
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
}
Now I want to allow a user to segue to another view by holding the same annotation. I tried to use and if and else statement in the code above but the Long press gesture doesn't work unless I tap the annotation first to activate the function so the if and else statement can start working. But I dont want the user to tap then hold. I just want them to either tap or hold down on the annotation.
Thank You for your answers in advance
I'm not familiar with the Mapbox API but if there's no proper delegate method try your own custom implementation with uigesturerecognizer and delegation.
set your gesture recognizer on the annotation view:
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPressDetected))
annotation.view.addGestureRecognizer(longPressGestureRecognizer)
make a delegate
weak var delegate: AnnotationViewDelegate?
and a protocol AnnotationViewDelegate in Annotation subclass:
protocol AnnotationViewDelegate: class {
func annotationDidDetectLongPress()
}
implement long press handler and notify the delegate about long tap inside
func longPressDetected(sender: UILongPressGestureRecognizer) {
// here you should notify the delegate
delegate?.annotationDidDetectLongPress()
}
assign delegate to self in controller and implement
func annotationDidDetectLongPress() {
// done
}
I made an app where a Mapbox map is loaded in a view and tracks the user's location with the following code:
func mapView(mapView: MGLMapView, didUpdateUserLocation userLocation: MGLUserLocation?) {
print(userLocation)
}
This code works fine on it's own as a ViewController, but when I add the view to a scrollview with addChildViewController, the code doesn't run. Any ideas?
I am working with a MKMapView that is placed on the third VC (MapViewController: UIViewController) in a tabbed application controller (AppTabController: UITabViewController). If I understand UITabViewController correctly, the MapViewController will not be instantiated until the user navigates to it.
The MKMapView is linked to the MapViewController via the outlet
#IBOutlet weak var mapView: MKMapView!
MapViewController conforms to the MKMapViewDelegate protocol through an extension to MapViewController and I’ve set the MKMapView delegate in the viewDidLoad method of MapViewController.
extension MapViewController: MKMapViewDelegate {
// delegate methods
}
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
}
In viewDidLoad of MapViewController I call showMyLocation() to centre the map on the user’s location in a 1 km. by 1 km. region and show their annotation.
The same method is linked to a “User” button on MapViewController’s nav bar which allows the user to return to their location if they want to.
#IBAction func showMyLocation() {
let region = MKCoordinateRegionMakeWithDistance(mapView.userLocation.coordinate, 1000, 1000)
mapView.setRegion(mapView.regionThatFits(region), animated: true)
}
I am not using a CLLocationManager to determine the user’s location. Because MKMapView is able to return the user’s location to the app.
Answers I've found so far point towards a CLLocationManager approach.
I am a little unsure about what appears to be a timing dependency in obtaining the user’s coordinates from MKMapView.
If I start the app and navigate immediately to the MapViewController tab the coordinates returned by mapView.userLocation.coordinate are 0,0
However if I start the app and wait for a minute or so before going to the MapViewController tab the coordinates are the expected ones for my location.
Finally, if I start the app and navigate immediately to the MapViewController the coordinates are 0,0 as above but if I immediately tap the “User” button the coordinates immediately update to the expected ones without the delay.
My solution so far is to implement the didUpdateUserLocation delegate method to tell me when MKMapView has obtained a valid location for the user.
func mapView(mapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation) {
if self.rideLocations.isEmpty {
self.showUserLocation()
}
}
My question is have I implemented the necessary pattern to deal with MKMapView user location behaviour timing?
My objective is to have the user’s location properly displayed on the MKMapView regardless of when they navigate to the tab that has the map on it but to avoid overuse of the device location services.
Thanks for all the answers so far - they’ve been a massive help in my Swift / IOS journey!
I know this is an old thread, but I thought I would add my two cents in case it helps someone else. To solve this problem you can implement the mapView delegate method mapView(_:viewFor:) which gets called every time an annotation is added to the map. This includes the user location. Just add the code at the top of the method. It's only called once when the MKUserLocation annotation is added to the mapView. In viewDidLoad disable the button.
`func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
showMyLocation()
enable your button here.
return nil
}
//other code here.`
I get to know after searching that idleAtCameraPosition and didChangeCameraPosition this methods are called when the map moves .
How can i write this method for swift? I have set delegate to CLLocationManagerDelegate and GMSMapViewDelegate but still this methods are not called. I have written method as below:
func mapView(mapView: GMSMapView!, didChangeCameraPosition position: GMSCameraPosition!) {
print(position)
}
func mapView(mapView:GMSMapView!,idleAtCameraPosition position:GMSCameraPosition!)
{
print(position)
}
But my method is not getting called.
Also I want to customise info window just like done here : Custom Info Window for Google Maps . But can't find the methods how to do same in swift. I am new to swift s o not getting this.
Maybe too late, but you must extend the class with GMSMapViewDelegate. For example:
class NearMeViewController: CLLocationManagerDelegate, GMSMapViewDelegate
Then, how Ztan says, you have to delegate your map with:
self.mapView.delegate = self
With this, the method didChangeCameraPosition will respond every time that that camera's position is changed.
Hope it helps.
You need to import the GMSMapViewDelegate at the top of your class
put self.mapView.delegate = self in your viewDidLoad()
and then you can use this method
func mapView(mapView: GMSMapView, idleAtCameraPosition position: GMSCameraPosition) {
// You can use the position.target for get the current camera position
}