Google Maps 'Did Long Press At' shows no response in Swift - swift

I'm trying to print out the current latitude and longitude when the user long pressed at the map:
Here's what I'm currently working on
//
// TrangChuViewController.swift
//
//
import UIKit
import GoogleMaps
class TrangChuViewController: UIViewController {
#IBOutlet weak var detailDirection: UILabel!
#IBOutlet weak var mapView: GMSMapView!
let locationManager = CLLocationManager()
var originLatitude: Double = 0
var originLongtitude: Double = 0
var destinationLatitude: Double = 0
var destinationLongtitude: Double = 0
var travelMode = TravelModes.driving
let directionService = DirectionService()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
mapView.settings.myLocationButton = true
mapView.isMyLocationEnabled = true
self.mapView.delegate = self
if CLLocationManager.authorizationStatus() != .authorizedWhenInUse {
locationManager.requestWhenInUseAuthorization()
} else {
locationManager.startUpdatingLocation()
}
self.detailDirection.isHidden = true
}
fileprivate func direction() {
self.mapView.clear()
let origin: String = "\(originLatitude),\(originLongtitude)"
let destination: String =
"\(destinationLatitude),\(destinationLongtitude)"
let marker = GMSMarker(position: CLLocationCoordinate2D(latitude: destinationLatitude, longitude: destinationLongtitude))
marker.map = self.mapView
self.directionService.getDirections(origin: origin,
destination: destination,
travelMode: travelMode) { [weak self] (success) in
if success {
DispatchQueue.main.async {
self?.drawRoute()
if let totalDistance = self?.directionService.totalDistance,
let totalDuration = self?.directionService.totalDuration {
self?.detailDirection.text = totalDistance + ". " + totalDuration
self?.detailDirection.isHidden = false
}
}
} else {
print("error direction")
}
}
}
fileprivate func drawRoute() {
for step in self.directionService.selectSteps {
if step.polyline.points != "" {
let path = GMSPath(fromEncodedPath: step.polyline.points)
let routePolyline = GMSPolyline(path: path)
routePolyline.strokeColor = UIColor.red
routePolyline.strokeWidth = 3.0
routePolyline.map = mapView
} else {
return
}
}
}
#IBAction func bicycling(_ sender: Any) {
self.travelMode = TravelModes.walking
self.direction()
self.afterDirection()
}
#IBAction func walking(_ sender: Any) {
self.travelMode = TravelModes.bicycling
self.direction()
self.afterDirection()
}
#IBAction func driving(_ sender: Any) {
self.travelMode = TravelModes.driving
self.direction()
self.afterDirection()
}
#IBAction func transit(_ sender: Any) {
self.travelMode = TravelModes.transit
self.direction()
self.afterDirection()
}
fileprivate func afterDirection() {
self.directionService.totalDistanceInMeters = 0
self.directionService.totalDurationInSeconds = 0
self.directionService.selectLegs.removeAll()
self.directionService.selectSteps.removeAll()
}
}
extension TrangChuViewController: CLLocationManagerDelegate {
//Handle incoming location events.
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
manager.stopUpdatingLocation()
if let location: CLLocation = locations.last {
let locationLatitude = location.coordinate.latitude
let locationLongtitude = location.coordinate.longitude
self.originLatitude = locationLatitude
self.originLongtitude = locationLongtitude
let camera = GMSCameraPosition.camera(
withLatitude: locationLatitude,
longitude: locationLongtitude, zoom: zoomLevel)
if mapView.isHidden {
mapView.isHidden = false
mapView.camera = camera
} else {
mapView.animate(to: camera)
}
}
}
// Handle authorization for the location manager.
func locationManager(_ manager: CLLocationManager,
didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
manager.startUpdatingLocation()
}
}
// Handle location manager errors.
func locationManager(_ manager: CLLocationManager,
didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
}
}
extension TrangChuViewController: GMSMapViewDelegate {
func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) {
mapView.delegate = self
let marker = GMSMarker(position: coordinate)
print("You tapped : \(marker.position.latitude),\(marker.position.longitude)")
self.destinationLatitude = coordinate.latitude
self.destinationLongtitude = coordinate.longitude
marker.map = self.mapView
}
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
mapView.delegate = self
}
}
Whenever I pressed on the Map, it shows no response at all. I have followed all other methods on Stack Overflow like
Setting the ViewController's delegate to mapView inside the mapView method and inside the ViewDidLoad but nothing helps.

Related

Route Between two A and B location

There is no error but I can not get the location from my current location to what I search. Can someone please help. It says this with I click on the Car logo to get directions: MKDirectionsErrorCode=7, NSLocalizedDescription=Directions Not Available}
I am only missing the line to get to the direction. When I click on the car logo, it just does not do anything but zoom out to my current location. I am missing anything or did something wrong?
Here is my code:
protocol HandleMapSearch {
func dropPinZoomIn(placemark:MKPlacemark)
}
class ViewController: UIViewController {
#IBOutlet weak var mapView: MKMapView! // Handle the Map Kit View
var selectedPin:MKPlacemark? = nil //Any incoming placemarks
// Destination for directions*********
var destination:MKMapItem = MKMapItem()
var MyPosition = CLLocationCoordinate2D()
var resultSearchController:UISearchController? = nil // Keep the UISearchController in memory after it's created
var locationManager = CLLocationManager() // Core Location
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest // Accuracy level
locationManager.requestWhenInUseAuthorization() // Triggers the location permission dialog
locationManager.startUpdatingLocation()
//locationManager.requestLocation() // Trigers a one-time location request
// Set up the search results table
let locationSearchTable = storyboard!.instantiateViewController(withIdentifier: "LocationSearchTable") as! LocationSearchTable
resultSearchController = UISearchController(searchResultsController: locationSearchTable)
resultSearchController?.searchResultsUpdater = locationSearchTable
// Set up the search bar
let searchBar = resultSearchController!.searchBar
searchBar.sizeToFit()
searchBar.placeholder = "Search for places"
navigationItem.titleView = resultSearchController?.searchBar
// Configure the UISearchController appearance
resultSearchController?.hidesNavigationBarDuringPresentation = false
resultSearchController?.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
locationSearchTable.mapView = mapView // Passes along a handle of the mapView
locationSearchTable.handleMapSearchDelegate = self // Handles the map search
}
//Getting direction of location
#objc func getDirections(sender: AnyObject){
if let selectedPin = selectedPin {
let mapItem = MKMapItem(placemark: selectedPin)
//let launchOptions = [MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving]
//mapItem.openInMaps(launchOptions: launchOptions)
let request = MKDirectionsRequest()
request.source = MKMapItem.forCurrentLocation()
request.destination = destination
request.requestsAlternateRoutes = false
let directions = MKDirections(request: request)
// 8.
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
let route = response.routes[0]
self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
}
}
/*
directions.calculate(completionHandler: {(response: MKDirectionsResponse!, error: Error!) in
if error != nil {
print("Error \(error)")
} else {
self.displayRout(response)
var overlays = self.mapView.overlays
for route in response.routes {
self.mapView.add(route.polyline, level: MKOverlayLevel.aboveRoads)
for next in route.steps {
print(next.instructions)
}
}
}
})
}
*/
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
}
//destination = MKMapItem(placemark: selectedPin!)
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController : CLLocationManagerDelegate {
// When user responds to the permission dialog
private func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
// When location information comes back (Zoom to the user's current location)
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
//****
MyPosition = location.coordinate
locationManager.stopUpdatingLocation()
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.setRegion(region, animated: true)
}
}
// Print out the error
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error finding location: \(error.localizedDescription)")
}
}
// Searches the location and city/state
extension ViewController: HandleMapSearch {
func dropPinZoomIn(placemark:MKPlacemark){
// cache the pin
selectedPin = placemark
// clear existing pins
mapView.removeAnnotations(mapView.annotations)
let annotation = MKPointAnnotation()
annotation.coordinate = placemark.coordinate
annotation.title = placemark.name
if let city = placemark.locality,
let state = placemark.administrativeArea {
annotation.subtitle = "\(city) \(state)"
}
mapView.addAnnotation(annotation)
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegionMake(placemark.coordinate, span)
mapView.setRegion(region, animated: true)
}
}
// Shows Pins and Car Logo
extension ViewController : MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.pinTintColor = UIColor.red
pinView?.canShowCallout = true
let smallSquare = CGSize(width: 30, height: 30)
let button = UIButton(frame: CGRect(origin: CGPoint.zero, size: smallSquare))
button.setBackgroundImage(UIImage(named: "Car"), for: .normal)
button.addTarget(self, action: #selector(getDirections), for: .touchUpInside)
pinView?.leftCalloutAccessoryView = button
return pinView
}
}
Have a look at below code for reference hope it helps :
1 using two locations here as source and as destination and drawing a path according to locations
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
let sourceLocation = CLLocationCoordinate2D(latitude: 40.759011, longitude: -73.984472)
let destinationLocation = CLLocationCoordinate2D(latitude: 40.748441, longitude: -73.985564)
// 3.
let sourcePlacemark = MKPlacemark(coordinate: sourceLocation, addressDictionary: nil)
let destinationPlacemark = MKPlacemark(coordinate: destinationLocation, addressDictionary: nil)
// 4.
let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
// 5.
let sourceAnnotation = MKPointAnnotation()
sourceAnnotation.title = "Times Square"
if let location = sourcePlacemark.location {
sourceAnnotation.coordinate = location.coordinate
}
let destinationAnnotation = MKPointAnnotation()
destinationAnnotation.title = "Empire State Building"
if let location = destinationPlacemark.location {
destinationAnnotation.coordinate = location.coordinate
}
// 6.
self.mapView.showAnnotations([sourceAnnotation,destinationAnnotation], animated: true )
// 7.
let directionRequest = MKDirectionsRequest()
directionRequest.source = sourceMapItem
directionRequest.destination = destinationMapItem
directionRequest.transportType = .walking
// Calculate the direction
let directions = MKDirections(request: directionRequest)
// 8.
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
let route = response.routes[0]
self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Output :

Getting user's location not working after Swift 4 update

I've just updated to the Xcode 9 and Swift 4 and it has broken at lot of my functions. One of which being how I get the user's location, zoom in on it on launch, detecting annotation selection and various other tasks. They don't work at all. My view controller class code is below.
import UIKit
import MapKit
import Firebase
import FirebaseDatabase
import Pulley
import CoreLocation
class ChildMapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
let manager = CLLocationManager()
var isInitialized = false
func startBackgroundLocationUpdates() {
self.manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
manager.pausesLocationUpdatesAutomatically = true
manager.activityType = .fitness
manager.allowsBackgroundLocationUpdates = true
manager.startMonitoringSignificantLocationChanges()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
if !isInitialized {
isInitialized = true
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
mapView.setRegion(region, animated: true)
self.mapView.showsUserLocation = true
}
}
struct loc {
let title: String
let latitude: Double
let longitude: Double
}
var locs = [
loc(title: "New York, NY", latitude: 40.713054, longitude: -74.007228),
]
func placeAnnotations() {
let annotations = locs.map { location -> MKAnnotation in
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
annotation.title = location.title
return annotation
}
mapView.addAnnotations(annotations)
}
var position:PulleyPosition!
func mapView(_ didSelectmapView: MKMapView, didSelect view: MKAnnotationView) {
Shared.shared.annotation = view.annotation!
if Shared.shared.annotation is MKUserLocation {
Shared.shared.nameString = "My Location"
} else {
loadData()
}
}
func mapView(_ mapView: MKMapView, didDeselect view:
MKAnnotationView) {
let drawerContent = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DrawerViewController")
if let drawer = self.parent?.parent as? PulleyViewController {
drawer.setDrawerContentViewController(controller: drawerContent, animated: false)
drawer.setDrawerPosition(position: PulleyPosition.partiallyRevealed, animated: true)
}
}
func loadData() {
let number = (Shared.shared.annotation?.title)!
if let number = number {
let ref = FIRDatabase.database().reference()
ref.child("safehouses").child("\(number)").observeSingleEvent(of: .value, with: { snapshot in
let snapDict = snapshot.value as? NSDictionary
let name = snapDict?["name"] as? String
let phone = snapDict?["phone"] as? String
let current = CLLocation(latitude: (self.manager.location?.coordinate.latitude)!, longitude: (self.manager.location?.coordinate.longitude)!)
let destination = CLLocation(latitude: Shared.shared.annotation.coordinate.latitude, longitude: Shared.shared.annotation.coordinate.longitude)
let distance2 = current.distance(from: destination)
let distance1 = round(distance2)
if distance1 >= 1000 {
if distance1 < 10000 {
let distance3 = distance1/1000
let distance = Double(round(10*distance3)/10)
Shared.shared.typeString = "Safehouse · " + String(distance) + " km"
} else {
let distance3 = distance1/1000
let distance = round(distance3)
Shared.shared.typeString = "Safehouse · " + String(distance) + " km"
}
} else {
let distance = self.forTailingZero(temp: distance1)
Shared.shared.typeString = "Safehouse · " + distance + " m"
}
if let name = name {
if let phone = phone {
Shared.shared.nameString = name
Shared.shared.phoneString = phone
let drawerContent = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NewDrawerViewController")
if let drawer = self.parent?.parent as? PulleyViewController {
drawer.setDrawerContentViewController(controller: drawerContent, animated: false)
drawer.setDrawerPosition(position: PulleyPosition.partiallyRevealed, animated: true)
}
}
}
})
}
}
func forTailingZero(temp: Double) -> String{
var tempVar = String(format: "%g", temp)
return tempVar
}
func loop() {
let ref = FIRDatabase.database().reference()
ref.child("safehouses").observeSingleEvent(of: .value, with: { snapshot in
let snapDict = snapshot.value as? NSDictionary
let ii = snapDict?["number"] as? Int
let iii = Int(ii!)
var i = 1
while i <= iii{
let name = String(i)
ref.child("safehouses").child("\(i)").observeSingleEvent(of: .value, with: { snapshot in
let snapDict = snapshot.value as? NSDictionary
let longitude = snapDict?["longitude"]
as? String
let latitude = snapDict?["latitude"] as? String
if let longitude = longitude {
if let latitude = latitude {
let latitude1 = Double(latitude)
if let latitude1 = latitude1 {
let longitude1 = Double(longitude)
if let longitude1 = longitude1 {
self.locs.append(loc(title: name, latitude: latitude1, longitude: longitude1))
self.placeAnnotations()
}
}
}
}
})
i = i + 1
}
})
}
#IBOutlet weak var menuButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
self.revealViewController().rearViewRevealWidth = 175
self.revealViewController().toggleAnimationType = SWRevealToggleAnimationType.easeOut
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
loop()
mapView.delegate = self
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestAlwaysAuthorization()
Shared.shared.mapView = self.mapView
startBackgroundLocationUpdates()
}
}
final class Shared {
static let shared = Shared()
var nameString : String!
var phoneString : String!
var annotation : MKAnnotation!
var mapView : MKMapView!
var typeString : String!
}
First add these property in info.plist
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>description1</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>description2</string>
<key>NSLocationUsageDescription</key>
<string>description3</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>accept to get location</string>
<key>UIBackgroundModes</key>
And then after copy this view controller in your project
import UIKit
import CoreLocation
class ViewController: UIViewController,CLLocationManagerDelegate {
var locationManager:CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
determineMyCurrentLocation()
// Do any additional setup after loading the view.
}
func determineMyCurrentLocation() {
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager!.allowsBackgroundLocationUpdates = true
locationManager!.pausesLocationUpdatesAutomatically = false
let value = locationManager.startMonitoringSignificantLocationChanges()
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didStartMonitoringFor region: CLRegion) {
print("ankur :- \(region)")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
print("user latitude = \(userLocation.coordinate.latitude)")
print("user longitude = \(userLocation.coordinate.longitude)")
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
{
print("Error \(error)")
}
}
Last step :- Open Capabilities -> In background modes -> click on location updates
If any query comment it
You need to add these keys in info plist :
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>

locationManager not being recognized as a class variable

I am trying to implement the locationManager methods and the let locationManager = CLLocation() variable is not being recognized anywhere in the code. The errors showed up when I added the didUpdateLocations and didFailWithError methods. Im trying to get the current location from the user as the view loads. Without the methods mentioned above the app breaks on the centerMapOnLocation method.
Here is my code:
import Foundation
import UIKit
import Firebase
import FirebaseDatabase
import CoreLocation
import MapKit
class MainViewController: UIViewController, CLLocationManagerDelegate{
var ref: FIRDatabaseReference!
var refHandle: UInt!
let locationManager: CLLocationManager = CLLocationManager()
let regionRadius: CLLocationDistance = 1000
var currentLocation: CLLocation!
let geoCoder = CLGeocoder()
var placemark: CLPlacemark?
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var userEmailLabel: UILabel!
#IBOutlet weak var pickUpAddress: UITextField!
override func viewDidLoad() {
ref = FIRDatabase.database().reference()
////
locationManager.delegate = self
locationManager.requestLocation()
print(locationManager.requestLocation())
////
////
refHandle = ref.observeEventType(FIRDataEventType.Value, withBlock: { (snapshot) in
let dataDict = snapshot.value as! [String: AnyObject]
print((dataDict))
})
let userID: String = FIRAuth.auth()!.currentUser!.uid
ref.child("users").child(userID).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
let userEmail = snapshot.value!["email"] as! String
self.userEmailLabel.text = userEmail
})
////
////
centerMapOnLocation()
super.viewDidLoad()
////
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
print("locations: \(locations)")
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("error: \(error)")
}
}
func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status != CLAuthorizationStatus.Denied{
locationManager.startUpdatingLocation()
}
}
func centerMapOnLocation() {
currentLocation = CLLocation.init(latitude: (locationManager.location?.coordinate.latitude)!, longitude: (locationManager.location?.coordinate.longitude)!)
let coordinateRegion = MKCoordinateRegionMakeWithDistance(locationManager.location!.coordinate, regionRadius * 2.0, regionRadius * 2.0)
mapView.setRegion(coordinateRegion, animated: true)
}
func translateLocation() {
geoCoder.reverseGeocodeLocation(currentLocation, completionHandler: { placemarks, error in
if error == nil && placemarks!.count > 0 {
self.placemark = placemarks![0] as CLPlacemark
self.pickUpAddress.text = self.stringFromPlacemark(self.placemark!)
}
})
}
func stringFromPlacemark(placemark: CLPlacemark) -> String { // 1
var line1 = ""
if let s = placemark.subThoroughfare {
line1 += s + " "
}
if let s = placemark.thoroughfare {
line1 += s
}
var line2 = ""
if let s = placemark.locality {
line2 += s + " "
}
if let s = placemark.administrativeArea {
line2 += s + " "
}
if let s = placemark.postalCode {
line2 += s }
return line1 + "\n" + line2
}
#IBAction func pickCurrentLocation(sender: AnyObject) {
translateLocation()
}
#IBAction func signOutButton(sender: AnyObject) {
try! FIRAuth.auth()!.signOut()
if let storyboard = self.storyboard {
let viewController = storyboard.instantiateViewControllerWithIdentifier("LoginViewController")
self.presentViewController(viewController, animated: false, completion: nil)
}
}
}
I have not found an answer after a while now. Help is going to be really appreciated.
Thanks.
Remove the top-level closing brace somewhere on line 75 and everything will be fine, it builds for me, the thing is it sees these functions as global ones.

How to find the user's location in swift?

Hello I am developing an application for ios and one of it's functions has to find the user's current location. Here is my code:
import UIKit
import MapKit
import CoreLocation
import SwiftyJSON
struct City {
let name : String
let location : CLLocation
let description :String
let imageName : String
func distanceTo(location:CLLocation) -> Int
{
let distanceMeters = location.distanceFromLocation(self.location)
let distanceKilometers = distanceMeters / 1000.00
return Int(round(100 * distanceKilometers) / 100)
}
}
class FirstViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var LabelTest: UILabel!
#IBOutlet weak var Slider: UISlider!
#IBOutlet weak var LabelValueSlider: UILabel!
var MySliderCurrentValue = Double()
var manager = CLLocationManager()
var userLoc: CLLocationCoordinate2D!
{
willSet{
self.orderCitysByProximity()
self.filterCitysByProximity(Int(self.Slider.value))
self.LocateMe(manager)
}
}
var cities = [City]()
var nearbyCities = [City]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let path: String = NSBundle.mainBundle().pathForResource("cities", ofType: "json") as String!
let jsonData = NSData(contentsOfFile: path) as NSData!
//let ReadableJSON = JSON ( data:jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil )
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.MutableContainers) as! [String:AnyObject]
for city in jsonObject["cities"] as! [[String:AnyObject]] {
//let coordinates = position["Position"] as! [String:CLLocationDegrees]
let cityName = city["Name"] as! String
let latitude = city["Latitude"] as! Double
let longitude = city["Longitude"] as! Double
let description = city["Description"] as! String
let image = city["Image"] as! String
let location = CLLocation(latitude: latitude, longitude: longitude)
let city = City(name: cityName, location: location,description: description, imageName: image)
cities.append(city)
// print(cities)
}
self.orderCitysByProximity()
self.filterCitysByProximity(Int(self.Slider.value))
} catch let error as NSError {
print(error)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func SliderChange(sender: UISlider) {
let MySliderCurrentValue: String = String(Int(sender.value))
LabelValueSlider.text = MySliderCurrentValue
self.filterCitysByProximity(Int(sender.value))
}
#IBAction func goToTableView()
{
if let tableViewController = self.storyboard?.instantiateViewControllerWithIdentifier("tableViewController") as? TableViewController
{
tableViewController.cities = self.nearbyCities
self.navigationController?.pushViewController(tableViewController, animated: true)
}
}
func filterCitysByProximity(kilometers:Int)
{
self.nearbyCities.removeAll()
for city in self.cities {
if(city.distanceTo(self.userLoc) <= kilometers*2)
{
self.nearbyCities.append(city)
}
}
self.LabelTest.text = "you have \(self.nearbyCities.count) cities nearby"
let OrderedArray = self.nearbyCities.sort({ $0.distanceTo(self.userLoc) < $1.distanceTo(self.userLoc) })
self.nearbyCities = OrderedArray
}
func orderCitysByProximity()
{
let OrderedArray = self.cities.sort({ $0.distanceTo(self.userLoc) < $1.distanceTo(self.userLoc) })
self.cities = OrderedArray
}
#IBAction func LocateMe(sender: AnyObject) {
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userlocation: CLLocation = locations[0] as CLLocation
manager.stopUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: userlocation.coordinate.latitude, longitude: userlocation.coordinate.longitude)
self.userLoc = location
}
}
On the bottom you will see the func locationManager, where I am trying to find the user's current location. Would you please advise me how to start this function so that the app recognise when I type userLoc. userLoc are the coordinations of the user and I have to use them in other functions like func filterCitysByProximity, and the rest, which you can see in the code.
Reason of your problem :-
When you call the delegate of the CLLocationManager in viewDidLoad() it takes some time to retrieve the usersCurrent Location , but even before usersLocation could relay back to you, your functions requiring usersCurrent Location were being triggered as you had called them in viewDidLoad() thus causing the error!
your Code should look like this:-
import UIKit
import MapKit
import CoreLocation
import SwiftyJSON
struct City {
let name : String
let location : CLLocation
let description :String
let imageName : String
func distanceTo(location:CLLocation) -> Int
{
let distanceMeters = location.distanceFromLocation(self.location)
let distanceKilometers = distanceMeters / 1000.00
return Int(round(100 * distanceKilometers) / 100)
}
}
class FirstViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var LabelTest: UILabel!
#IBOutlet weak var Slider: UISlider!
#IBOutlet weak var LabelValueSlider: UILabel!
var MySliderCurrentValue = Double()
var locationManager = CLLocationManager()
var userLoc : CLLocation!
var cities = [City]()
var nearbyCities = [City]()
override func viewDidLoad() {
super.viewDidLoad()
let path: String = NSBundle.mainBundle().pathForResource("cities", ofType: "json") as String!
let jsonData = NSData(contentsOfFile: path) as NSData!
do {
let jsonObject = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.MutableContainers) as! [String:AnyObject]
for city in jsonObject["cities"] as! [[String:AnyObject]] {
//let coordinates = position["Position"] as! [String:CLLocationDegrees]
let cityName = city["Name"] as! String
let latitude = city["Latitude"] as! Double
let longitude = city["Longitude"] as! Double
let description = city["Description"] as! String
let image = city["Image"] as! String
let location = CLLocation(latitude: latitude, longitude: longitude)
let city = City(name: cityName, location: location,description: description, imageName: image)
cities.append(city)
}
} catch let error as NSError {
print(error)
}
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.requestWhenInUseAuthorization()
locationManager.startMonitoringSignificantLocationChanges()
locationManager.startUpdatingLocation()
if locationManager.respondsToSelector(#selector(locationManager.requestWhenInUseAuthorization)) {
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
}
else {
locationManager.startUpdatingLocation()
}
}
#IBAction func SliderChange(sender: UISlider) {
let MySliderCurrentValue: String = String(Int(sender.value))
LabelValueSlider.text = MySliderCurrentValue
if userLoc != nil{
self.filterCitysByProximity(Int(sender.value), location: userLoc)
}else{
let alertC : UIAlertController = UIAlertController(title: "Iwin", message: "UserLocation Not Updated wait a while", preferredStyle: .Alert)
let okAction : UIAlertAction = UIAlertAction(title: "oK", style: .Default, handler: { (okActn) in
print("User pressed ok")
})
alertC.addAction(okAction)
alertC.popoverPresentationController?.sourceView = view
alertC.popoverPresentationController?.sourceRect = view.frame
self.presentViewController(alertC, animated: true, completion: nil)
}
}
//Segue to .. :-
#IBAction func goToTableView()
{
if let tableViewController = self.storyboard?.instantiateViewControllerWithIdentifier("tableViewController") as? TableViewController
{
tableViewController.cities = self.nearbyCities
print(nearbyCities)
self.navigationController?.pushViewController(tableViewController, animated: true)
}
}
#IBAction func LocateMe(sender: AnyObject) {
}
//Class Functions call :-
func filterCitysByProximity(kilometers:Int, location: CLLocation)
{
self.nearbyCities.removeAll()
for city in self.cities {
if(city.distanceTo(location) <= kilometers*2)
{
self.nearbyCities.append(city)
}
}
self.LabelTest.text = "you have \(self.nearbyCities.count) cities nearby"
let OrderedArray = self.nearbyCities.sort({ $0.distanceTo(location) < $1.distanceTo(location) })
self.nearbyCities = OrderedArray
}
func orderCitysByProximity(location: CLLocation)
{
let OrderedArray = self.cities.sort({ $0.distanceTo(location) < $1.distanceTo(location) })
self.cities = OrderedArray
}
//Location Manager Functions :-
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
userLoc = locations[0] as CLLocation
locationManager.stopUpdatingLocation()
print(userLoc)
self.orderCitysByProximity(userLoc)
self.filterCitysByProximity(Int(self.Slider.value), location : userLoc)
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .AuthorizedWhenInUse {
print("authorised call came . . . . ")
locationManager.startUpdatingLocation()
}
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError){
print(error.localizedDescription)
locationManager.stopUpdatingLocation()
}
}
Add privacy - location usage description : Result to your info.plist
Also if your didUpdateLocations function doesn't get called
reset your location Services by going into settings->General->Reset
Try google, you will find multiple questions

Print nothing instead of nil

I created a view that shows the users location on a map and displays the users location in two labels in the view. Its not always there is a subThoroughfare, so "nil" is printed in in the labels. What can I do to just print in nothing instead of "nil" in the label?
Thanks for your help
import UIKit
import CoreLocation
import MapKit
class Kart: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet var myMap: MKMapView!
var locationManager = CLLocationManager()
#IBOutlet var adress: UILabel!
#IBOutlet var adress2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("Feil")
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var userLocation:CLLocation = locations[0] as! CLLocation
locationManager.stopUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude, longitude: userLocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegion(center: location, span: span)
myMap.setRegion(region, animated: true)
CLGeocoder().reverseGeocodeLocation(userLocation, completionHandler: { (placemarks, error) -> Void in
if (error != nil) {
println(error)
} else {
if let p = CLPlacemark(placemark: placemarks?[0] as! CLPlacemark) {
var subThoroughfare:String = ""
if (p.subThoroughfare != nil) {
subThoroughfare = p.subThoroughfare
}
self.adress.text = "\(p.thoroughfare) \(p.subThoroughfare)"
self.adress2.text = " \(p.postalCode) \(p.subLocality)"
}
}
})
}
self.adress.text = "\(p.thoroughfare) \(p.subThoroughfare)"
uses p.subThoroughfare instead of subThoroughfare. Also, you can use the nil coalescing operator for this (??)
var subThoroughfare = p.subThoroughfare ?? ""
will evaluate to p.subThoroughfare if it is not nil, otherwise it will evaluate to ""
so:
var subThoroughfare = p.subThoroughfare ?? ""
self.adress.text = "\(p.thoroughfare) \(subThoroughfare)"
self.adress2.text = " \(p.postalCode) \(p.subLocality)"
Move the line that prints subThoroughfare into your if statement:
if (p.subThoroughfare != nil) {
subThoroughfare = p.subThoroughfare
self.adress.text = "\(p.thoroughfare) \(p.subThoroughfare)"
}
else
self.adress.text = "\(p.thoroughfare)"
Also: It doesn't look like you're using that subThoroughfare variable.