How to open google maps when tapped any where on gmsmapview - swift

I have a classified application. When posting an ad you need to give your location as a viewer i can see the marked location and map-view but the marked location only open in the google maps when i tap the google button on the bottom left corner of gmsmapview. I want the user to be enable to open the marked location in google maps when he taps anywhere in the map. Is there any function that detects tap anywhere on the map.

This code will check if google maps are installed. If yes it will open location in maps else will open the location in safari.
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
if(self.current_long != "" && self.current_lat != "")
{
//Add your latitude
let lat: String = self.current_lat
//Add your longitude
let lon: String = self.current_long
if (UIApplication.shared.canOpenURL(URL(string:"comgooglemaps://")!)) {
UIApplication.shared.open(URL(string:"comgooglemaps://?center=\(lat),\(lon)&zoom=14&views=traffic&q=\(lat),\(lon)")!, options: [:], completionHandler: nil)
}else{
print("Cannot open maps")
if let urlDestination = URL.init(string: "https://www.google.com/maps/?center=\(lat),\(lon)&zoom=14&views=traffic&q=\(lat),\(lon)"){
UIApplication.shared.open(urlDestination, options: [:], completionHandler: nil)
}
}
}
}

Related

How do I call a function repeatedly in ARKit from ViewController to recognise objects / images?

I'm designing guided tour app, and I want the app to recognize the landmarks when it's visible to the back camera, and then present info about the landmark using ARkit
In ARKit, I'm trying to recognise landmarks visible to the camera, and using Google's Firebase / Cloud Vision to identify them.
My problem is I can't get current image from camera in UIimage format to send to Google Cloud API
I've added a button that takes a picture, and written another function that passes the captured image to Firebase and recognises it, but I want the app to recognise the landmark automatically, without having to take a photo.
#IBAction func cameraButton(_ sender: Any) {
let snapShot = self.sceneView.snapshot()
getLandmarkName(image: snapShot)
UIImageWriteToSavedPhotosAlbum(snapShot, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}
func getLandmarkName(image: UIImage) {
//property for creating instance of Google Cloud Landmark recognition service
let cloudDetector = vision.cloudLandmarkDetector(options: cloudOptions)
//property for storing the image from buffer as a vision image
let cloudImage = VisionImage(image: image)
if cloudImage != nil {
print("image object received")
}
cloudDetector.detect(in: cloudImage) { landmarks, error in
guard error == nil, let landmarks = landmarks, !landmarks.isEmpty else {
// ...
self.dismiss(animated: true, completion: nil)
//self.landmarkName.text = "No Landmark Detected"
print("no landmark detected")
return
}
// Recognized landmarks
for landmark in landmarks {
let landmarkName = landmark.landmark!
print("landmark detected: \(landmarkName)")
}
}//close landmark detection
}//close func
I've tried calling the fn swift getLandmarkName from viewDidUpdate and it only calls it once at the start, which is useless for recognising landmarks as you need it to call repeatedly when holding phone to recognise landmark.
Apparently there's this function as part of ARSessionDelegate
optional func session(_ session: ARSession,
didUpdate frame: ARFrame)
https://developer.apple.com/documentation/arkit/arsessiondelegate/2865611-session
and it looks exactly like what's required, but I can't figure out how to use or call it. I've tried calling the getLandmarkName from this function but it doesn't do anything.

How to get Address of selected location from google place picker marker

UPDATE - Found the Solution and Here is the Sample Project if anyone looking for the same solution. This will get City, Country, Postal code and LocalAdress(subLocality) from the coordinates and nearby locations.
https://github.com/SwiftGuides/Google_Place_Picker
I have implemented google place picker API in my project so that I can move picker and get nearby locations and also the location of the exact street where my picker is located.
I want the address of place picker custom location like (unnamed road, Panchkula, India) instead of (37°19'1464"N 122°01'74.724"W).
In android google place picker API when we Click "select this address" for custom location, It shows a popup and sets the location in string format (unnamed road, Panchkula, India) instead of (37°19'1464"N 122°01'74.724"W)
I want something like that
Here is an image of the current status
https://ibb.co/HYD5TKP
Please help !!
import UIKit
import GooglePlaces
import GooglePlacePicker
import GoogleMaps
class ViewController: UIViewController,GMSPlacePickerViewControllerDelegate {
#IBOutlet weak var addressLabel: UILabel!
#IBOutlet weak var placeNameLabel: UILabel!
#IBOutlet weak var coordinatesLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
// To receive the results from the place picker 'self' will need to conform to
// GMSPlacePickerViewControllerDelegate and implement this code.
func placePicker(_ viewController: GMSPlacePickerViewController, didPick place: GMSPlace) {
// Dismiss the place picker, as it cannot dismiss itself.
viewController.dismiss(animated: true, completion: nil)
print("Place name \(place.name)")
print("PostalCode\(place.addressComponents)")
print("Place address \(place.formattedAddress)")
print("Place attributions \(place.attributions)")
placeNameLabel.text = place.formattedAddress
//Get address Seperated like city,country,postalcode
let arrays : Array = place.addressComponents!
for i in 0..<arrays.count {
let dics : GMSAddressComponent = arrays[i]
let str : String = dics.type
if (str == "country") {
print("Country: \(dics.name)")
}
else if (str == "administrative_area_level_1") {
print("State: \(dics.name)")
}
else if (str == "administrative_area_level_2") {
print("City: \(dics.name)")
}
else if (str == "postal_code"){
print("PostalCode:\(dics.name)")
addressLabel.text = dics.name // this is only to get postalcode of the selected nearby location
}
}
}
func placePickerDidCancel(_ viewController: GMSPlacePickerViewController) {
// Dismiss the place picker, as it cannot dismiss itself.
viewController.dismiss(animated: true, completion: nil)
print("No place selected")
}
#IBAction func pickPlaceButton(_ sender: Any) {
let config = GMSPlacePickerConfig(viewport: nil)
let placePicker = GMSPlacePickerViewController(config: config)
//This delegate has to be called here to proper working of cancle and selected location feature , it is not mentioned in the official documentation
placePicker.delegate = self
present(placePicker, animated: true, completion: nil)
}
}
Just get the location from the marker and call the below function which will return a return Address string
func getPlaceAddressFrom(location: CLLocationCoordinate2D, completion: #escaping (_ address: String) -> Void) {
let geocoder = GMSGeocoder()
geocoder.reverseGeocodeCoordinate(location) { response, error in
if error != nil {
print("reverse geodcode fail: \(error!.localizedDescription)")
} else {
guard let places = response?.results(),
let place = places.first,
let lines = place.lines else {
completion("")
return
}
completion(lines.joined(separator: ","))
}
}
}

Cannot get locationInView: for this type of NSTouch assertion error when trying to retrieve location

I'm trying to retrieve the mouse location after a user clicks on a specific SCNNode. I eventually want to perform a hit test to determine which SCNNode was clicked. I have the following code but once I run the project I get an assertion error stating: "Cannot get locationInView: for this type of NSTouch". Any help would be appreciated.
override func touchesBegan(with event: NSEvent) {
let touch = event.touches(for: self.view)
if #available(OSX 10.12.2, *) {
let location = touch.first?.location(in: self.view)
let hitResults = sceneView.hitTest(location!, options: nil)
} else {
// Fallback on earlier versions
}
}
-locationInView: will only work for touches of type NSTouchTypeDirect. If you have a Mac with a Touch Bar, pressing it will lead to an event with a touch of type NSTouchTypeIndirect which has no location on the screen.

Swift - GoogleMaps SDK get coordinates on touch

I am new to swift and the Google Maps SDK, and was wondering how to get the coordinates of where the user has tapped using the Google Maps SDK. For example if a user holds their finger down on a certain place on a map, a annotation is created there. I would really appreciate your help, thanks.
In the GMSMapViewDelegate there is a method named: mapView:didLongPressAtCoordinate: which is called after a long-press gesture at a particular coordinate. See the reference here.
By implementing this method you could then add a marker to the map view:
func mapView(mapView: GMSMapView!, didLongPressAtCoordinate coordinate: CLLocationCoordinate2D) {
let marker = GMSMarker(position: coordinate)
marker.title = "Hello World"
marker.map = mapView
}
For a tap gesture a similar delegate method can be implemented called mapView:didTapAtCoordinate: which can be used in a similar way:
func mapView(mapView: GMSMapView!, didTapAtCoordinate coordinate: CLLocationCoordinate2D) {
print("Tapped at coordinate: " + String(coordinate.latitude) + " "
+ String(coordinate.longitude))
}
Try this
extension ViewController: GMSMapViewDelegate {
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D)
{
print("Tapped at coordinate: " + String(coordinate.latitude) + " "
+ String(coordinate.longitude))
}
}
For Swift 5.0+
First, make sure you have added GMSMapViewDelegate delegate to your ViewController Class
Add this default function in your class
func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) {
debugPrint("Coordinates: ", coordinate)
}
If you just want coordinates, then above function is perfect for you But if you want to create Marker or get local address from touch then see below function
func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) {
let marker = GMSMarker(position: coordinate) //Add this line if you want to add marker
let decoder = CLGeocoder()
decoder.reverseGeocodeLocation(CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)) { placemarks, err in
if let placeMark = placemarks?.first {
let plName = placeMark.name ?? placeMark.subThoroughfare ?? placeMark.thoroughfare! //Place Name
var address : String! = "" //This will be the local address
if let subLocality = placeMark.subLocality ?? placeMark.name {
address.append(subLocality)
address.append(", ")
}
if let city = placeMark.locality ?? placeMark.subAdministrativeArea {
address.append(city)
address.append(", ")
}
if let state = placeMark.administrativeArea, let country = placeMark.country {
address.append(state)
address.append(", ")
address.append(country)
}
// Add Marker:
marker.title = plName
marker.snippet = address
marker.appearAnimation = .pop
marker.map = mapView
}
}
}
This Function does not only get coordinates but creates a Marker with all the details fetched from the coordinates(Like PlaceName, city, state,country etc.) too
If you just want local address, then remove all the code lines related to marker
The reason why i have used CLGeocoder and not GMSGeocoder from
GoogleMapDelegate is that Apple's CLGeocoder is much more precise
in getting the place-name while GMSGeocoder does not fetch
place-name accurately.
Also Note that : Apple's Geocoding requests are rate-limited for each app, so making too many requests in a short period of time may
cause some of the requests to fail.

How can I find a user's location using Google Maps SDK for Swift?

So I am trying to get it so I open the app and it starts off at the user's location. The problem is I am getting "User's location is unknown" in the output box. I have location enabled as seen in the code below, so I am wondering if something else might be causing this issue. Help would be appreciated thanks.
import UIKit
import GoogleMaps
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let camera = GMSCameraPosition.cameraWithLatitude(-33.86,
longitude: 151.20, zoom: 6)
let mapView = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
mapView.accessibilityElementsHidden = false
mapView.myLocationEnabled = true
self.view = mapView
if let mylocation = mapView.myLocation {
print("User's location: \(mylocation)")
} else {
print("User's location is unknown")
}
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(-33.86, 151.20)
marker.title = "Sydney"
marker.snippet = "Australia"
marker.map = mapView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Have you tried using CLLocationManager() ?
Try the tutorial below, this should show you how to get the user's location. This will take you through asking the user for permission to see their location, down to reverse geocoding the location to display the address they are at, using GMSGeocoder()
[https://www.raywenderlich.com/109888/google-maps-ios-sdk-tutorial][1]
[1]: Ray Wenderlich
Hope that helps
I tried this so:
Set a custom String for the authorization request when in use (or whatever you need) in "Privacy - Location When In Use Usage Description" (or simply NSLocationWhenInUseUsageDescription) of my Info.plist properties file. Then this will ask you authorize finding your location.
Set the properly delegate (GMSMapViewDelegate) in your view: for example
class MapView: UIViewController, GMSMapViewDelegate{...}
And finally set delegate to your GMSMapView instance. In my case mapView:
let mapView = GMSMapView.map(withFrame: frameMapViewContainer, camera: camera)
mapView.delegate = self