I'm using the Google Place Picker APi and wanted to know if there is a way to remove the back button and the search button and also prevent the map from moving around, that is created with the _placePicker = [[GMSPlacePicker alloc] initWithConfig:config]; ?
if not, is there an alternative i can use that provides same functionality? Basically, I want the the closest points of interest near a users location..
Thanks.
I'm also trying to figure that out. So far, what I've come up with is to combine GMSMapView and GMSPlacesClient into your own custom viewcontroller.
To gather the nearby points of interest, you'll use the GMSPlacesClient:
placesClient = GMSPlacesClient.sharedClient()
likelyPlace = [GMSPlaces]()
placesClient.currentPlaceWithCallback({ (placeLikelihoods, error) in
if let error = error {
print("Error with Current place: \(error.localizedDescription)")
} else {
if let likelihoodList = placeLikelihoods{
for likelihood in likelihoodList.likelihoods {
let place = likelihood.place
self.likelyPlaces.append(place)
}
}
}
})
this will put the nearby places in your likelyPlaces array. Then it's up to you how you'd want to display the contents. Maybe put them in a tableView or as annotations on the map.
Hope this helps.
Related
I'm relatively new to iOS and Mapbox development. I'm working on an app where a user can freely manipulate a map full of places they have saved.
When they reach a zoom-level that is completely filled by the geography of a city, I would like to display the name of the city which they are viewing in a banner-style view, even if a city label is not within view on the map (as is often the case when zoomed in).
Here's a screenshot of the UI for context.
I'm trying to query the Mapbox tileset for the city name using the following code:
func mapViewRegionIsChanging(_ mapView: MGLMapView) {
let zoomLevel = mapView.zoomLevel
if zoomLevel >= 14.0 {
// layer identifier taken from layer name in Mapbox Studio
let layerIdentifier = "place-city-lg-n"
let screenRect = UIScreen.main.bounds
let cityName = mapView.visibleFeatures(in: screenRect, styleLayerIdentifiers: Set([layerIdentifier]))
print(cityName)
}
I think this code doesn't work because the label is not onscreen at the specified zoom level.
I'm wondering if using visibleFeaturesInRect is the best approach for my need—is there a better way to retrieve city name regardless of visible elements and zoom level?
For this task I'd recommend using MapboxGeocoder from Mapbox. It is for getting information about the city/village.
you can install pod:
pod 'MapboxGeocoder.swift', '~> 0.12'
and use this code:
let geocoder = Geocoder.shared
func mapViewRegionIsChanging(_ mapView: MGLMapView) {
let geocodeOptions = ReverseGeocodeOptions(coordinate: mapView.centerCoordinate)
geocodeOptions.allowedScopes = [.place]
let _ = geocoder.geocode(geocodeOptions) { (placemarks, attribution, error) in
guard let placemark = placemarks?.first else { return }
print(placemark.name)
print(placemark.qualifiedName)
}
}
you can add your conditions and it really helps to solve your task
I've been working on an app to annotate an MKMapView with all nightlife locations near a user. I have implemented a recenter function that is called by a SwiftUI button. The recenter works fine based on CLLocationManager.location, but after any MKLocalSearch query, the setRegion stops working. It must be the setRegion because the correct lat/long are still printed. I also know it is not due to the annotations because the same bug happens when the annotation add/remove part is commented out. Does it possibly have something to do with linking the searchRequest.region and map.region? manager is the CLLocationManager instance, map is the MapView
func recenter(){
print("Recenter called")
guard let center = manager.location?.coordinate else{
print("Could not get location for recenter")
return
}
let newRegion = MKCoordinateRegion(center: center, latitudinalMeters: 1000, longitudinalMeters: 1000)
print("\(center.latitude) and \(center.longitude)")
map.setRegion(newRegion, animated: true)
}
func queryAndAnnotate(){
let searchRequest = MKLocalSearch.Request()
searchRequest.naturalLanguageQuery = "nightlife"
searchRequest.region = map.region
let search = MKLocalSearch(request: searchRequest)
search.start{response, error in
guard let response = response else {
Alert(title:Text("Alert"), message: Text("Error: \(error?.localizedDescription ?? "Unknown Error")"))
return
}
var mapItemPlacemarks: [MKPointAnnotation] = []
self.barsList = []
for i in response.mapItems{
let x = MKPointAnnotation()
x.coordinate = i.placemark.coordinate
x.title = i.name
mapItemPlacemarks.append(x)
}
self.map.removeAnnotations(mapItemPlacemarks)
self.map.addAnnotations(mapItemPlacemarks)
}
}
MKLocalSearch.start calls the completionHandler in background task.
In this handler you are updating your mapView instance in background task.
Make sure to call all update methods of mapView in main task (removeAnnotations, addAnnotations, setRegion)
btw in
self.map.removeAnnotations(mapItemPlacemarks)
self.map.addAnnotations(mapItemPlacemarks)
you are removing mapItemPlacemarks that do not exist in the mapView. This makes no sense, but it is not your problem.
As it turns out the problem was coming from a dynamic update to a ScrollView. The ScrollView was within a slide up drawer that sat above the MapView on the Z axis. When the ScrollView was updated with the results from the local search, the MapView object lost track of userLocation (read 0,0) and the region could not be programmatically changed. I ended up fixing the problem by ditching the recenter() function altogether and instead implementing an MKUserTrackingButton within its own UIViewRepresentable (for SwiftUI). The MKUserTrackingButton is how the system maps cycles through user tracking modes. You can read the docs for it here: https://developer.apple.com/documentation/mapkit/mkusertrackingbutton
I'm using mapkit and able to get Address for a particular location
let firstPlacemark = placemarks,
let addressDictionary = firstPlacemark.addressDictionary else { return }
// let street = addressDictionary["Street"]
// let city = addressDictionary["City"]
// let state = addressDictionary["State"]
// let zip = addressDictionary["ZIP"]
print(addressDictionary.description)
if let array = addressDictionary["FormattedAddressLines"] as? [Any] {
let address = array.map { "\($0)" }.joined(separator: ",\n")
print("Address : \(address)")
}
But Can we get more information like reviews contact no. images etc. Like Apple Maps shows (Observe Screeenshot)
Is there any API available in iOS for this or it will be provided via TripAdvisor???
P.S: I don't want to Any Google API.
Dear down voters if don't know the answers then kindly don't waste my points. It's easy to downvote, but you never know how much efforts has been added to earn those points.
OR Kindly provide me solution or show me if question is duplicate.
You can use Tripadvisor API
https://developer-tripadvisor.com/content-api/documentation/
ex.
http://api.tripadvisor.com/api/partner/2.0/location/155507?key=YOURKEY
I want to show annotations on the locations I get from my geofire database but even after writing the code and not getting any error no annotations are visible on the map.
My variable is
var vendorStore: Dictionary<String,Int>
My code in viewDidLoad
for (key,_) in KeyValue{
geoFireKeyValue.getLocationForKey(key, withCallback: { (location, error) in
if (error != nil) {
print("An error occurred getting the location for \"firebase-hq\": \(String(describing: error?.localizedDescription))")
} else if location != nil {
let annotation = MKPointAnnotation()
self.lat = (location?.coordinate.latitude)!
self.long = (location?.coordinate.longitude)!
annotation.coordinate = CLLocationCoordinate2D(latitude: self.lat, longitude: self.long)
self.mapView.addAnnotation(annotation)
self.mapView.showAnnotations(self.mapView.annotations, animated: true)
} else {
print("GeoFire does not contain a location for \"firebase-hq\"")
}
})
}
I am successfully getting the latitude and longitude in print statement as well but still no annotations are showing up. I tried moving the code else outside the for loop (just to check if any annotation show up) with some hard coded lat long coordinates and the annotation showed successfully. But still they aren't showing up when set in the geofire function within the loop (also not showing up in the loop outside the geofire function even with hard coded values). So kindly help me in resolving this issue.
I found the issue. The main problem was that I was sending the data from the previous view controller. That view controller was changed before the data was sent from the previous controller. So the solution is to make sure that data is set in the variable of the next view controller before the view actually appears. That's what I am trying to achieve now.
I'm trying to build an app showing my favorite spots with swift.
I already store my spot information GeoPoints from parse.com. But I still can't manage to show retrieve the data (spot name and GeoPoints) and pass it to MKMapView. Can someone show me an example to do this?
I also find this question Parse objects as AnnonationPoints, but since I just started learning swift, I don't understand about Objective-C.
really appreciate if anyone can help me. Thank you in advance.
After googling, and trial and error, this is my best answer right now. Hope helps for others!
// retrieve data from parse.com
let query:PFQuery = PFQuery(className: "SpotList")
query.orderByAscending("SpotName")
query.findObjectsInBackgroundWithBlock{ (objects:[AnyObject]! , error:NSError!)-> Void in
if !(error != nil){
for object in objects! {
self.SpotNames.append(object["SpotName"] as String)
self.SpotGeoPoints.append(object["SpotLocation"] as PFGeoPoint)
self.SpotLocationLatitudes.append(self.SpotGeoPoints.last?.latitude as CLLocationDegrees!)
self.SpotLocationLongitudes.append(self.SpotGeoPoints.last?.longitude as CLLocationDegrees!)
var annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(self.SpotLocationLatitudes.last!, self.SpotLocationLongitudes.last!)
annotation.title = self.SpotNames.last!
self.mainMap.addAnnotation(annotation)
self.mainMap.showsUserLocation = true
}
}
}