Using MKDirections to get Map Directions and Routes not working - ios

i am trying to provide the user with a navigation direction with the click of a button. But for some reason it doesn't seem to be working.
#IBAction func directionToDestination(sender: AnyObject) {
getDirections()
}
func getDirections(){
let request = MKDirectionsRequest()
let destination = MKPlacemark(coordinate: CLLocationCoordinate2DMake(place.latitude, place.longitude), addressDictionary: nil)
request.setSource(MKMapItem.mapItemForCurrentLocation())
request.setDestination(MKMapItem(placemark: destination))
request.transportType = MKDirectionsTransportType.Automobile
var directions = MKDirections(request: request)
directions.calculateDirectionsWithCompletionHandler({(response:
MKDirectionsResponse!, error: NSError!) in
if error != nil {
// Handle error
} else {
self.showRoute(response)
}
})
}
func showRoute(response: MKDirectionsResponse) {
for route in response.routes as! [MKRoute] {
placeMap.addOverlay(route.polyline,level: MKOverlayLevel.AboveRoads)
for step in route.steps {
println(step.instructions)
}
}
}
func mapView(mapView: MKMapView!, rendererForOverlay
overlay: MKOverlay!) -> MKOverlayRenderer! {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blueColor()
renderer.lineWidth = 5.0
return renderer
}
here is how my viewDidLoad() looks
manager = CLLocationManager()
manager.delegate = self
manager.requestWhenInUseAuthorization()
placeMap.delegate = self
can someone please point what am i doing wrong with a sample code in swift ?

Here is a full working sample for getting the users location and getting directions to a destination coordinate.
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
mapView.showsUserLocation = true
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
#IBAction func directionToDestinationButtonPressed(_ sender: UIButton) {
guard let userLocationCoordinate = UserLocation.shared.location?.coordinate else { return }
let directionRequest = MKDirections.Request()
directionRequest.source = MKMapItem(
placemark: MKPlacemark(
coordinate: userLocationCoordinate
)
)
directionRequest.destination = MKMapItem(
placemark: MKPlacemark(
coordinate: CLLocationCoordinate2D(latitude: 47.6205, longitude: -122.3493)
)
)
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate { (response, error) in
guard let response = response else { return }
let route = response.routes.first
if let line = route?.polyline {
self.mapView.addOverlay(line, level: .aboveRoads)
}
}
}
//MARK: - MKMapViewDelegate
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let polyLine = overlay as? MKPolyline {
let lineRenderer = MKPolylineRenderer(polyline: polyLine)
lineRenderer.strokeColor = .red
lineRenderer.lineWidth = 3
return lineRenderer
}
return MKOverlayRenderer()
}
//MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
UserLocation.shared.location = locations.first
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedWhenInUse:
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()
case .denied:
UserLocation.shared.location = nil
locationManager.requestWhenInUseAuthorization()
case .notDetermined:
UserLocation.shared.location = nil
locationManager.requestWhenInUseAuthorization()
default:
break
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Location Manager Error -> \(String(describing: error.localizedDescription))")
}
}
Add this class to hold the users location
class UserLocation {
static let shared = UserLocation()
var location: CLLocation?
}
In the Info.plist add this key and value
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location Usage Description Shown To The User</string>

I don't know if you added the two required strings into the plist project.
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription

Related

How can I show my current location in maps in Xcode?

I watched a few lessons on Youtube and now tried to get hands-on experience. I am pursuing a little project which involves a tabbed app where I tried on the first page to create a map with a button showing the current location. Pretty basic actually. But somehow it just doesn’t work and I don’t know what’s the issue. Someone from CodewithChris told me this “I would suggest breaking up your app into smaller components and making sure each one works before going on to the next. Try outputting your location first before plotting it on a map etc so you can localize bugs easier.” I just don’t understand what she means by smaller components. I really appreciate all the help I can get. Below is the code as good as possible. Thanks in advance for your help.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet var textFieldForAddress: UITextField!
#IBOutlet var getDirectionsButton: UIButton!
#IBOutlet var map: MKMapView!
var locationManger = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManger.delegate = self
locationManger.desiredAccuracy = kCLLocationAccuracyBest
locationManger.requestAlwaysAuthorization()
locationManger.requestWhenInUseAuthorization()
locationManger.startUpdatingLocation()
map.delegate = self
}
#IBAction func getDirectionsTapped(_ sender: Any) {
getAddress()
}
func getAddress() {
let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(textFieldForAddress.text!) { (placemarks, error) in
guard let placemarks = placemarks, let location = placemarks.first?.location
else {
print("No Location Found")
return
}
print(location)
self.mapThis(destinationCord: location.coordinate)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
}
func mapThis(destinationCord : CLLocationCoordinate2D) {
let souceCordinate = (locationManger.location?.coordinate)!
let soucePlaceMark = MKPlacemark(coordinate: souceCordinate)
let destPlaceMark = MKPlacemark(coordinate: destinationCord)
let sourceItem = MKMapItem(placemark: soucePlaceMark)
let destItem = MKMapItem(placemark: destPlaceMark)
let destinationRequest = MKDirections.Request()
destinationRequest.source = sourceItem
destinationRequest.destination = destItem
destinationRequest.transportType = .automobile
destinationRequest.requestsAlternateRoutes = true
let directions = MKDirections(request: destinationRequest)
directions.calculate { (response, error) in
guard let response = response else {
if let error = error {
print("Something is wrong :(")
}
return
}
let route = response.routes[0]
self.map.addOverlay(route.polyline)
self.map.setVisibleMapRect(route.polyline.boundingMapRect, animated: true)
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let render = MKPolylineRenderer(overlay: overlay as! MKPolyline)
render.strokeColor = .blue
return render
}
}
If you want to show the user location and have the map track it, you need to set two properties on the map view - showsUserLocation and userTrackingMode. In order for the map to have access to the user location you must receive whenInUse authorisation from the user, using CLocationManager.
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet var textFieldForAddress: UITextField!
#IBOutlet var getDirectionsButton: UIButton!
#IBOutlet var map: MKMapView!
var locationManger = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManger.requestWhenInUseAuthorization()
map.showsUserLocation = true
map.userTrackingMode = .follow
}
If you are running on the simulator then you need to simulate a location using the Debug menu in the simulator.
Okay, this information is surprising hard to find (just getting your own location!) — even after watching tutorials I had a hard time. But basically what you're missing is mapView.showsUserLocation = true
Here's the full code, if you need it...
import UIKit
import CoreLocation
import MapKit
class RadiusMapLocationViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
let coordinate = CLLocationCoordinate2DMake(33.97823607957177, -118.43823725357653)
var locationManager : CLLocationManager = CLLocationManager()
// Authorize use of location
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
mapView.showsUserLocation = (status == .authorizedAlways)
}
// Entering region
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
showAlert(withTitle: "You've entered \(region.identifier)", message: "Happy hopping!")
}
// Exiting region
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
showAlert(withTitle: "You've exited \(region.identifier)", message: "")
}
// Creating region and notifying when exit / enter
func region(with geotification: Geotification) -> CLCircularRegion {
let region = CLCircularRegion(center: geotification.coordinate,
radius: geotification.radius,
identifier: geotification.identifier)
region.notifyOnEntry = (geotification.eventType == .onEntry)
region.notifyOnExit = !region.notifyOnEntry
return region
}
// Monitoring region, if not "error"
func startMonitoring(geotification: Geotification) {
if !CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
showAlert(withTitle:"Error", message: "Geofencing is not supported on this device!")
return
}
}
func stopMonitoring(geotification: Geotification) {
for region in locationManager.monitoredRegions {
guard let circularRegion = region as? CLCircularRegion,
circularRegion.identifier == geotification.identifier else { continue }
locationManager.stopMonitoring(for: circularRegion)
}
}
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
mapView.userTrackingMode = .follow
mapView.showsUserLocation = true
// Region of coordinate
mapView.region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 800, longitudinalMeters: 800)
mapView.region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
let title = "Marina Bar Hop"
let restaurantAnnotation = MKPointAnnotation()
restaurantAnnotation.coordinate = coordinate
restaurantAnnotation.title = title
mapView.addAnnotation(restaurantAnnotation)
let regionRadius = 300.0
let circle = MKCircle(center: coordinate, radius: regionRadius)
mapView.addOverlay(circle)
self.locationManager.requestAlwaysAuthorization()
self.locationManager.delegate = self as? CLLocationManagerDelegate
//Zoom to user location
if let userLocation = locationManager.location?.coordinate {
let viewRegion = MKCoordinateRegion(center: userLocation, latitudinalMeters: 200, longitudinalMeters: 200)
mapView.setRegion(viewRegion, animated: false)
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.strokeColor = UIColor.red
circleRenderer.lineWidth = 1.0
return circleRenderer
}
}
I have a few additional features on here if you need them. And it sounds like maybe you want to add a pin on the user's current location? It's included in this code too. I hope this helps! :)

How to get nearby gas station and show direction to user with swift?

For a school project, I'm trying to get all nearby gas stations and create annotations for them and when the user click on one of these, I would like to get him the direction to go there.
this is the Maps controller that I implement by searching on internet and tutoriels:
import UIKit
import MapKit
import CoreLocation
protocol MapsControllerDelegate : class {
func mapsViewControllerDidSelectAnnotation(mapItem :MKMapItem)
}
class MapsController : UIViewController {
#IBOutlet weak var maps: MKMapView!
weak var delegate :MapsControllerDelegate!
let locationManager = CLLocationManager()
let regionInMeters: Double = 1000
override func viewDidLoad() {
super.viewDidLoad()
checkLocationServices()
}
func setupLocationManager(){
locationManager.delegate = self as! CLLocationManagerDelegate
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
func centerViewOnUserLocation(){
if let location = locationManager.location?.coordinate{
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
maps.setRegion(region, animated: true)
}
}
func checkLocationServices(){
if CLLocationManager.locationServicesEnabled(){
//setup the location manager.
setupLocationManager()
checkLocationAuthorization()
}
else{
//Show alert let the user know how to do it.
}
}
func checkLocationAuthorization(){
switch CLLocationManager.authorizationStatus(){
case .authorizedWhenInUse:
maps.showsUserLocation = true
centerViewOnUserLocation()
locationManager.startUpdatingLocation()
case .denied:
break
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .restricted:
break
case .authorizedAlways:
break
}
}
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
let annotationView = views.first!
if let annotation = annotationView.annotation {
if annotation is MKUserLocation {
centerViewOnUserLocation()
populateNearByPlaces()
}
}
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
let annotation = view.annotation as! PlaceAnnotation
self.delegate.mapsViewControllerDidSelectAnnotation(mapItem: annotation.mapItem)
}
func populateNearByPlaces(){
print("Im heeeeeerrrrreeeeeee")
if let location = locationManager.location?.coordinate{
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = "Gas Station"
request.region = region
let search = MKLocalSearch(request: request)
search.start { (response, error) in
guard let response = response else {
return
}
for item in response.mapItems {
print("I'm here")
print(item)
let annotation = PlaceAnnotation()
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
annotation.mapItem = item
DispatchQueue.main.async {
self.maps.addAnnotation(annotation)
}
}
}
}
}
}
extension MapsController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else {return}
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion.init(center: center, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
maps.setRegion(region, animated: true)
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
checkLocationAuthorization()
}
}
}
I don't have any errors or the app stops working but I'm not getting the results expected. In the Maps scene I'm just getting the user's actual location on the map and that's it.

MKPolyline isn't drawing on the map. How can I resolve this issue?

I am trying to draw an MKPolyline on a map. When I do a simulated run on the app, the location moves correctly but no line is drawn. How can I resolve this issue?
mapView.delegate = self
mapView.showsUserLocation = true
mapView.mapType = MKMapType(rawValue: 0)!
mapView.userTrackingMode = MKUserTrackingMode(rawValue: 2)!
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
mapView.mapType = MKMapType(rawValue: 0)!
}
override func viewWillAppear(_ animated: Bool) {
locationManager.startUpdatingHeading()
locationManager.startUpdatingLocation()
}
override func viewWillDisappear(_ animated: Bool) {
locationManager.stopUpdatingHeading()
locationManager.stopUpdatingLocation()
}
// MARK: - CLLocationManager delegate
func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) {
//drawing path or route covered
if let oldLocationNew = oldLocation as CLLocation?{
let oldCoordinates = oldLocationNew.coordinate
let newCoordinates = newLocation.coordinate
var area = [oldCoordinates, newCoordinates]
var polyline = MKPolyline(coordinates: &area, count: area.count)
mapView.add(polyline)
}
//calculation for location selection for pointing annoation
if let previousLocationNew = previousLocation as CLLocation?{
//case if previous location exists
if previousLocation.distance(from: newLocation) > 200 {
addAnnotationsOnMap(locationToPoint: newLocation)
previousLocation = newLocation
}
}
else{
//case if previous location doesn't exists
addAnnotationsOnMap(locationToPoint: newLocation)
previousLocation = newLocation
}
}
// MARK: - MKMapView delegate
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if (overlay is MKPolyline) {
var pr = MKPolylineRenderer(overlay: overlay)
pr.strokeColor = UIColor.red
pr.lineWidth = 5
return pr
}
return nil
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if startDate == nil {
startDate = Date()
} else {
print("elapsedTime:", String(format: "%.0fs", Date().timeIntervalSince(startDate)))
timeLabel.text="\(Date().timeIntervalSince(startDate))"
}
if startLocation == nil {
startLocation = locations.first
} else if let location = locations.last {
traveledDistance += lastLocation.distance(from: location)
print("Traveled Distance:", traveledDistance)
distanceLabel.text="\(traveledDistance)"
print("Straight Distance:", startLocation.distance(from: locations.last!))
}
lastLocation = locations.last
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
if (error as? CLError)?.code == .denied {
manager.stopUpdatingLocation()
manager.stopMonitoringSignificantLocationChanges()
}
}
MKPolyline should be drawn as the user moves.
The signature for mapView(_:rendererFor:) is incorrect. It has changed. It is now:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
switch overlay {
case let polyline as MKPolyline:
let renderer = MKPolylineRenderer(polyline: polyline)
renderer.strokeColor = .red
renderer.lineWidth = 5
return renderer
// you can add more `case`s for other overlay types as needed
default:
fatalError("Unexpected MKOverlay type")
}
}
If you add a print statement or breakpoint inside your current method, I believe you will find that it’s not being called. And, of course, make sure that you’ve set the delegate of your map view, either in IB or programmatically.
By the way, the old locationManager(_:didUpdateTo:from:) is deprecated. Use locationManager(_:didUpdateLocations:) instead. You’ll have to maintain your own reference to the savedLocation and the savedPolyline:
var savedLocation: CLLocation?
var savedPolyline: MKPolyline?
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last(where: { $0.horizontalAccuracy >= 0 }) else { return }
var polyline: MKPolyline?
if let oldCoordinate = savedLocation?.coordinate {
let coordinates = [oldCoordinate, location.coordinate]
polyline = MKPolyline(coordinates: coordinates, count: coordinates.count)
mapView.addOverlay(polyline!)
}
// if you want to remove the old one
//
// if let savedPolyline = savedPolyline {
// mapView.removeOverlay(savedPolyline)
// }
//
// savedPolyline = polyline
savedLocation = location
// ...
}

No accuracy when recording CLLocationPoints in Swift

I'm working with a app to record walks, but I can't get the polylines to be as smooth as it looks in other apps, like runkeeper. I have tried with different activityType, desiredAccuracy and so on. I have tested on iPhone 5c, 6s and 7. It always looks like the example photo, it was recorded out in the open without any buildings near. Is there something I'm missing?
This is my viewDidLoad, viewWillAppear, viewDidAppear, locationManager and rendererFor overlay:
import UIKit
import MapKit
import CoreLocation
...
override func viewDidLoad() {
super.viewDidLoad()
myLocations = []
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.activityType = .fitness
manager.distanceFilter = 5
}
override func viewWillAppear(_ animated: Bool) {
//Map
logMap.delegate = self
logMap.mapType = MKMapType.standard
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
manager.allowsBackgroundLocationUpdates = true
logMap.userTrackingMode = MKUserTrackingMode(rawValue: 1)!
}
override func viewDidAppear(_ animated: Bool) {
let status = CLLocationManager.authorizationStatus()
if status == .notDetermined || status == .denied || status ==
.authorizedWhenInUse {
manager.requestAlwaysAuthorization()
manager.requestWhenInUseAuthorization()
manager.requestLocation()
}else{
manager.startUpdatingLocation()
logMap.showsUserLocation = true
}
if status != .denied {
manager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager,
didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
manager.requestLocation()
}
if status == .authorizedAlways {
logMap.showsUserLocation = true
logMap.mapType = MKMapType(rawValue: 0)!
//logMap.userTrackingMode = MKUserTrackingMode(rawValue: 3)!
manager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations
locations: [CLLocation]){
if(isLoging==true){
if(myLocations.count > 1){
self.distance = self.distance +
Int(locations[0].distance(from: myLocations.last!))
}
myLocations.append(locations[0])
setDistance()
}
// paint line
if (myLocations.count > 1){
let sourceIndex = myLocations.count - 1
let destinationIndex = myLocations.count - 2
let c1 = myLocations[sourceIndex].coordinate
let c2 = myLocations[destinationIndex].coordinate
var a = [c1, c2]
let polyline = MKPolyline(coordinates: &a, count: a.count)
logMap.add(polyline)
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.lineWidth = 4
return polylineRenderer
}
return MKPolylineRenderer(overlay: overlay)
}
Result:
Try to set distanceFilter to k​CLDistance​Filter​None. This will notify you of every movement, but will consume the most battery.
Even if you are outside of a building you still don't get perfect accuracy.
If I were to guess other fitness app assume that you don't run through buildings and stuff, so they adjust you path to match streets.
I know for a fact that Strava shows my path through buildings and gardens, because they don't get perfect accuracy.
Do this to get best accuracy to get your location everytime.
override func loadView() {
print("loadView called")
// Enable some map settings
map.isMyLocationEnabled = true
map.settings.myLocationButton = true
map.settings.compassButton = true
map.settings.scrollGestures = true
map.settings.zoomGestures = true
map.delegate = self
view = map
}
override func viewDidLoad() {
super.viewDidLoad()
print("ViewDidLoad called")
// Configuring location manager.
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()
}
Add Delegate in ViewController: CLLocationManagerDelegate, GMSMapViewDelegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locationManager function called")
// Fetch current location coordinates
let locValue:CLLocationCoordinate2D = (locationManager.location?.coordinate)!
currentLatitude = locValue.latitude
currentLongitude = locValue.longitude
print("Current Location = \(currentLatitude!), \(currentLongitude!)")
// Zoom to current location
let target = CLLocationCoordinate2D(latitude: currentLatitude!, longitude: currentLongitude!)
map.camera = GMSCameraPosition.camera(withTarget: target, zoom: 17)
locationManager.stopUpdatingLocation()
//DispatchQueue.main.asyncAfter(deadline: .now() + 1.75, execute: {self.webResponse()})
}

SWIFT: Core Location returning nil - how to call didUpdateLocations?

I have an issue with Core Location, I've followed the setup from
https://stackoverflow.com/a/24696878/6140339 this answer, and placed all my code in AppDelegate, but I can't figure out how to call it, so I created another function that does the same thing as didUpdateLocations, and called it inside my findMyLocation button, and it is only returning nil.
I have tried setting a custom location in Simulator, still nil, I tried using the debugger and setting a location, I even tried testing it on my iphone to see if i could get a location, and still nothing.
is there a way to call didUpdateLocations from my button?
Or am I just doing something else wrong that im missing.
here is my code in my viewController:
import UIKit
import Social
import CoreLocation
class FirstViewController: UIViewController{
//let social = socialFunctions()
let locationManager = CLLocationManager()
let location = locationFunctions()
var locationFixAchieved = false
var currentLocation = CLLocation()
#IBOutlet weak var locationLabel: UILabel!
#IBAction func findMyLocation(sender: AnyObject) {
updateLocation()
print("Location: \(locationManager.location)")
}
#IBAction func postToFacebookButton(sender: UIButton) {
postToFacebook()
}
#IBAction func postTweetButton(sender: UIButton) {
postToTwitter()
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//MARK: - SOCIAL FUNCTIONS
func postToFacebook(){
if(SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook)){
let socialController = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
//creates post with pre-desired text
socialController.setInitialText("")
presentViewController(socialController, animated: true, completion: nil)
}
}
func postToTwitter(){
if(SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter)){
let socialController = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
//creates post with pre-desired text
socialController.setInitialText("")
presentViewController(socialController, animated: true, completion: nil)
}
}
//MARK: - LOCATION FUNCTIONS
func updateLocation() {
let locations = [CLLocation]()
if (locationFixAchieved == false) {
locationFixAchieved = true
let locationArray = locations as NSArray
let locationObj = locationArray.lastObject as? CLLocation
let coord = locationObj?.coordinate
if coord?.latitude != nil {
locationLabel.text = ("Location \r\n Latitude: \(coord?.latitude) \r\n Longitude: \(coord?.longitude)")
print("Latitude: \(coord?.latitude)")
print("Longitude: \(coord?.longitude)")
} else {
locationLabel.text = ("Could not find location")
print("LAT & LONG are nil")
}
}
}
}
Here is the code i added to my appDelegate
import UIKit
import CoreLocation
let fvc = FirstViewController()
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var locationManager: CLLocationManager!
var seenError : Bool = false
var locationFixAchieved: Bool = false
var locationStatus : NSString = "Not Started"
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
initLocationManager();
return true
}
func initLocationManager() {
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
locationManager.delegate = self
CLLocationManager.locationServicesEnabled()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
locationManager.stopUpdatingLocation()
if (error == true) {
if (seenError == false) {
seenError = true
print(error)
}
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locations = [CLLocation]()
if (locationFixAchieved == false) {
locationFixAchieved = true
let locationArray = locations as NSArray
let locationObj = locationArray.lastObject as? CLLocation
let coord = locationObj?.coordinate
print("Latitude: \(coord?.latitude)")
print("Longitude: \(coord?.longitude)")
//fvc.locationLabel.text = ("Location \r\n Latitude: \(coord?.latitude) \r\n Longitude: \(coord?.longitude)")
}
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
var shouldIAllow = false
switch status {
case CLAuthorizationStatus.Restricted:
locationStatus = "Restricted Access to location"
case CLAuthorizationStatus.Denied:
locationStatus = "User denied access to location"
case CLAuthorizationStatus.NotDetermined:
locationStatus = "Status not determined"
default:
locationStatus = "Allowed location Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasBeenUpdated", object: nil)
if (shouldIAllow == true) {
NSLog("Location Allowed")
//Start location services
locationManager.startUpdatingLocation()
} else {
NSLog("Denied access: \(locationStatus)")
}
}
Following dan's comment(thank you) all I had to do was delete the first line, and it shows the coordinates, i have yet to figure out how to call my function to change the label text, but i will post that when i figure it out. EDIT: posted solution below
I changed
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locations = [CLLocation]()
if (locationFixAchieved == false) {
locationFixAchieved = true
let locationArray = locations as NSArray
let locationObj = locationArray.lastObject as? CLLocation
let coord = locationObj?.coordinate
print("Latitude: \(coord?.latitude)")
print("Longitude: \(coord?.longitude)")
//fvc.locationLabel.text = ("Location \r\n Latitude: \(coord?.latitude) \r\n Longitude: \(coord?.longitude)")
}
}
deleting let locations = [CLLocation]()
This is how i called it when i press the button.
func updateLocation() {
let manager = CLLocationManager()
let locValue : CLLocationCoordinate2D = (manager.location?.coordinate)!;
let long = locValue.longitude
let lat = locValue.latitude
print(long)
print(lat)
locationLabel.text = ("Location \r\nLatitude: \(lat) \r\nLongitude: \(long)")
}

Resources