Skip to content

Instantly share code, notes, and snippets.

@satriawarn
Last active November 15, 2022 05:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save satriawarn/173be342d498019fc8004616a000e31e to your computer and use it in GitHub Desktop.
Save satriawarn/173be342d498019fc8004616a000e31e to your computer and use it in GitHub Desktop.
import UIKit
import GoogleMaps
import GooglePlaces
import CoreLocation
class ViewController: UIViewController {
var locationManager: CLLocationManager!
var resultsViewController: GMSAutocompleteResultsViewController?
var searchController: UISearchController?
var resultView: UITextView?
var currentLocation: CLLocation?
var placesClient: GMSPlacesClient!
@IBOutlet var mapView: GMSMapView!
override func viewDidLoad() {
//searchbox
resultsViewController = GMSAutocompleteResultsViewController()
resultsViewController?.delegate = self
searchController = UISearchController(searchResultsController: resultsViewController)
searchController?.searchResultsUpdater = resultsViewController
searchController?.searchBar.sizeToFit()
navigationItem.titleView = searchController?.searchBar
// When UISearchController presents the results view, present it in
// this view controller, not one further up the chain.
definesPresentationContext = true
// Prevent the navigation bar from being hidden when searching.
searchController?.hidesNavigationBarDuringPresentation = false
placesClient = GMSPlacesClient.shared()
}
}
/**
This extension inherit GMSAutoCompleteResult to handle
text from search bar, when user click one of result placemark
it will fetching directions api google maps
**/
extension ViewController: GMSAutocompleteResultsViewControllerDelegate {
func resultsController(_ resultsController: GMSAutocompleteResultsViewController,
didAutocompleteWith place: GMSPlace) {
searchController?.isActive = false
fetchRoute(from: locationManager.location!.coordinate, to: place.coordinate)
}
func fetchRoute(from source: CLLocationCoordinate2D, to destination: CLLocationCoordinate2D) {
//fetching google maps api with parameters coordinate origin and coordinate destination
let url = URL(string: "https://maps.googleapis.com/maps/api/directions/json?origin=\(source.latitude),\(source.longitude)&destination=\(destination.latitude),\(destination.longitude)&sensor=false&mode=driving&key=\(googleApiKey)")!
//process the result from fetching api
URLSession.shared.dataTask(with: url, completionHandler: {
(data, response, error) in
if(error != nil){
print("error")
}else{
DispatchQueue.main.async {
self.mapView.clear()
}
do{
//get the json from the result
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String : AnyObject]
let routes = json["routes"] as! NSArray
OperationQueue.main.addOperation({
for route in routes {
if let legs = (route as AnyObject) as? [String : AnyObject]{
let legs = legs["legs"] as! [[String : AnyObject]]
for leg in legs {
let durations:NSDictionary = (leg as NSDictionary).value(forKey: "duration") as! NSDictionary
let textDuration = durations.object(forKey: "text")
let distance:NSDictionary = (leg as NSDictionary).value(forKey: "distance") as! NSDictionary
let textDistance = distance.object(forKey: "text")
self.showEstimate(distance: textDistance as! String, duration: textDuration as! String)
let end_location: NSDictionary = (leg as NSDictionary).value(forKey: "end_location") as! NSDictionary
let textLat = end_location.object(forKey: "lat")
let textLong = end_location.object(forKey: "lng")
self.showPinPoint(latitude: textLat as! Double, longitude: textLong as! Double)
}
}
let routeOverviewPolyline:NSDictionary = (route as! NSDictionary).value(forKey: "overview_polyline") as! NSDictionary
let points = routeOverviewPolyline.object(forKey: "points")
self.drawPath(from: points as! String)
}
})
} catch let error as NSError{
print("error:\(error)")
}
}
}).resume()
}
/**
This function used to generate the polyline
using parameters of points from overview_polyline
also move camera for user visibility
**/
func drawPath(from polyStr: String){
let path = GMSPath.init(fromEncodedPath: polyStr)
let polyline = GMSPolyline.init(path: path)
. . .
}
/**
This function used to give user information
about the distance and duration
**/
func showEstimate(distance: String, duration: String){
. . .
}
/**
This function used to dropped pin
in location that have been choosen by user
**/
func showPinPoint(latitude lat: Double, longitude long: Double){
. . .
}
func resultsController(_ resultsController: GMSAutocompleteResultsViewController,
didFailAutocompleteWithError error: Error){
// TODO: handle the error.
print("Error: ", error.localizedDescription)
}
// Turn the network activity indicator on and off again.
func didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
func didUpdateAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
extension ViewController: CLLocationManagerDelegate {
// Handle incoming location events.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
. . .
}
// Handle authorization for the location manager.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
// Check accuracy authorization
let accuracy = manager.accuracyAuthorization
switch accuracy {
case .fullAccuracy:
. . .
case .reducedAccuracy:
. . .
@unknown default:
fatalError()
}
// Handle authorization status
switch status {
case .restricted:
. . .
case .denied:
. . .
case .notDetermined:
. . .
case .authorizedAlways, .authorizedWhenInUse :
. . .
@unknown default:
fatalError()
}
}
// Handle location manager errors.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment