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

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)")
}

Related

Cannot assign locationManager() function to DispatchQueue.main.async { * }

I am getting an error while trying to assign function locationManager() in the DispatchQueue.main.async {}, ill provide whole code and specific pic of error for more clarity --> Here
I got most of the code from SeanAllen on yt since I am new to swift and learning everyday so this code isn't my logic, and the function fetchAndReloadData() is my functionalists I created to get the lat and long from the API assigning to the correct car id since it will track Vehicles on map (car tracking app)
class MapViewController: UIViewController, MKMapViewDelegate {
var globalVechicle = [Vehicles]()
var id = "6438367CC43848B497FE4604AF465D6A"
let locationManager = CLLocationManager()
let regionInMeters: Double = 10000
#IBOutlet weak var mapView: MKMapView!
#IBAction func changeMapType(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
mapView.mapType = .standard
}else {
mapView.mapType = .satellite
}
}
#IBAction func closeButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
checkLocationServices()
}
func setupLocationManager() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
func centerViewOnUserLocation() {
if let location = locationManager.location?.coordinate {
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
mapView.setRegion(region, animated: true)
}
}
func checkLocationServices() {
if CLLocationManager.locationServicesEnabled() {
setupLocationManager()
checkLocationAuthorization()
} else {
// show alert they have to turn it on
}
}
func checkLocationAuthorization() {
switch CLLocationManager.authorizationStatus() {
case .authorizedWhenInUse:
mapView.showsUserLocation = true
centerViewOnUserLocation()
fetchAndReloadData()
locationManager.startUpdatingLocation()
break
case .denied:
// show alert instructing them how to turn on the permissions
break
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .restricted:
// Show an alert letting them know what's up
break
case .authorizedAlways:
break
#unknown default:
print("Error")
}
}
}
extension MapViewController: CLLocationManagerDelegate {
func fetchAndReloadData(){
APICaller.shared.getVehicles(for: id) {[weak self] (result) in
guard let self = self else { return }
switch result {
case .success(let vehicle):
self.globalVechicle = vehicle
DispatchQueue.main.async {
self.locationManager()
}
case .failure(let error):
print(error)
}
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let lattitude = globalVechicle[0].Latitude ,let longitude = globalVechicle[0].Longitude else { return }
let carLocation = CLLocationCoordinate2D(latitude: lattitude , longitude: longitude)
let region = MKCoordinateRegion.init(center: carLocation, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
mapView.setRegion(region, animated: true)
mapView.delegate = self
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
checkLocationAuthorization()
}
}

How to fix Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value?

I have a problem with the Users Location.
When im trying to build the program it gets this error code: (Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value)
My code:
import UIKit
import MapKit
class ViewController: UIViewController {
private let locationManager = CLLocationManager()
private var currentCoordinate: CLLocationCoordinate2D?
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
configerLocationServices()
}
private func configerLocationServices() {
locationManager.delegate = self
let status = CLLocationManager.authorizationStatus()
if status == .notDetermined {
locationManager.requestWhenInUseAuthorization()
} else if status == .authorizedAlways || status == .authorizedWhenInUse {
beginLocationUpdates(locationManager: locationManager)
}
}
private func beginLocationUpdates(locationManager: CLLocationManager) {
mapView.showsUserLocation = true //<--- the problem is here
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
private func zoomToLastestLocation(with coordinate: CLLocationCoordinate2D) {
let zoomRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: 10000, longitudinalMeters: 10000)
mapView.setRegion(zoomRegion, animated: true)
}
}
extension ViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("Did get latest Location")
guard let latestLocation = locations.first else { return }
if currentCoordinate == nil {
zoomToLastestLocation(with: latestLocation.coordinate)
}
currentCoordinate = latestLocation.coordinate
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print("The Status changed")
if status == .authorizedAlways || status == .authorizedWhenInUse {
self.beginLocationUpdates(locationManager: manager)
}
}
}
I don't know what im doing wrong, has anyone the solution?
Thank you in advance.
private func setNewLoaction(lat:CLLocationDegrees,long:CLLocationDegrees,markerTitle:String){
let center = CLLocationCoordinate2D(latitude: lat, longitude: long)
let camera = GMSCameraPosition.camera(withLatitude: lat, longitude: long, zoom: 15)
self.googleMapsView?.camera = camera
self.googleMapsView?.isMyLocationEnabled = true
let marker = GMSMarker(position: center)
marker.map = self.googleMapsView
marker.title = markerTitle
locationManager.stopUpdatingLocation()
}
//MARK:- MAP VIEW
private func setUpMap(){
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
self.googleMapsView = GMSMapView (frame: CGRect(x: 0, y: 0, width: self.view.frame.width-30, height: self.mapView.frame.height))
self.googleMapsView?.settings.compassButton = true
self.googleMapsView?.isMyLocationEnabled = true
self.googleMapsView?.settings.myLocationButton = true
self.mapView.addSubview(self.googleMapsView!)
}
I have called setUpMap in ViewDidload and this setLoaction function in GMSAutocompleteViewControllerDelegate =:
func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
destinationField.text = place.formattedAddress
destinationLatitude = place.coordinate.latitude
destinationLongitutude = place.coordinate.longitude
setNewLoaction(lat: destinationLatitude!, long: destinationLongitutude!, markerTitle: "Destination Location")
dismiss(animated: true, completion: nil)
}
you can call this anywhere as per you need, do remember to turn on location when asked for permission and if using in simlulator go to Features/Loaction/custom Location
I have now an other code for the same thing it is shorter than the old one.
Here is the code:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController {
#IBOutlet var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.requestWhenInUseAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.startUpdatingLocation()
mapView.showsUserLocation = true // <--- Crash
}
}
And now it gets the same problem as the old one :(

How to make the annotation appear on the Apple map via Swift?

So basically, I'm calling a Rest API to get all Bus Stops location, then put annotation of all bus stops within 5km from my current location on the map when a button is called. However, it is just not displaying, I can't seem to figure out the problem.
import UIKit
import MapKit
class MapKitViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet weak var GPSButton: UIButton!
var stopSearchResults: [Value] = []
var Annotations: [BusStopAnnotation] = []
let queryServices = QueryService()
let locationManager:CLLocationManager = CLLocationManager()
#IBOutlet weak var mapView: MKMapView!
var currentLocation: CLLocationCoordinate2D?
var counter: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.shared.isNetworkActivityIndicatorVisible = true
queryServices.GetAllBusStops(){
result in
UIApplication.shared.isNetworkActivityIndicatorVisible = false
if let result = result {
self.stopSearchResults = result.value
}
}
configureLocationService()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func configureLocationService() {
locationManager.delegate = self
let status = CLLocationManager.authorizationStatus()
if status == .notDetermined {
locationManager.requestAlwaysAuthorization()
} else if status == .authorizedAlways || status == .authorizedWhenInUse {
beginLocationUpdate(locationManager: locationManager)
}
}
private func beginLocationUpdate(locationManager: CLLocationManager) {
mapView.showsUserLocation = true
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
private func zoomToLatestLocation(with coordinate: CLLocationCoordinate2D) {
let zoomRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
mapView.setRegion(zoomRegion, animated: true)
}
#IBAction func GPSTrack(_ sender: Any) {
InputAllAnnotation(busStops: stopSearchResults)
print("Searching for nearby bus stops")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("Did get latest location")
guard let latestLocation = locations.first else { return }
if currentLocation == nil {
zoomToLatestLocation(with: latestLocation.coordinate)
}
currentLocation = latestLocation.coordinate
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print("The status changed")
if status == .authorizedAlways || status == .authorizedWhenInUse {
beginLocationUpdate(locationManager: manager)
}
}
func InputAllAnnotation(busStops: [Value]) {
for busStop in busStops{
let busStopObj = BusStopAnnotation(value: busStop)
Annotations.append(busStopObj)
let distance = busStop.GetDistance(latitude: Double(currentLocation?.latitude ?? 0), longitude: Double(currentLocation?.longitude ?? 0))
if distance < 5000 {
mapView.addAnnotation(busStopObj)
}
}
}
}
extension MapKitViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let busStopAnnotation = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier) as?
MKMarkerAnnotationView {
busStopAnnotation.animatesWhenAdded = true
busStopAnnotation.titleVisibility = .adaptive
busStopAnnotation.canShowCallout = true
return busStopAnnotation
}
return nil
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
print("The annotation was selected: \(String(describing: view.annotation?.title))")
}
}
final class BusStopAnnotation: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
var busStopCode: String?
init(value : Value) {
self.coordinate = value.GetLocationCoordinate2D()
self.title = value.roadName
self.subtitle = value.description
self.busStopCode = value.busStopCode
}
init(coordinate: CLLocationCoordinate2D, roadName: String?, description: String?, busStopCode: String?) {
self.coordinate = coordinate
self.title = roadName
self.subtitle = description
self.busStopCode = busStopCode
}
var region: MKCoordinateRegion {
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
return MKCoordinateRegion(center: coordinate, span: span)
}
}
You may need
self.mapView.delegate = self
import:
import UIKit
import MapKit
set class
class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
outlet your map
#IBOutlet weak var map: MKMapView!
Code:
let customPin : CLLocationCoordinate2D = CLLocationCoordinate2DMake(Latitude, Longitude)
let objectAnnotation = MKPointAnnotation()
objectAnnotation.coordinate = customPin
objectAnnotation.title = "Here's your custom PIN"
self.map.addAnnotation(objectAnnotation)
extra:
to set the camera near the PIN
let theSpan:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: 0.009, longitudeDelta: 0.009)
let pointLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(Latitude, Longitude)
let region:MKCoordinateRegion = MKCoordinateRegion(center: pointLocation, span: theSpan)
self.map.setRegion(region, animated: true)
move values depending how close/far you want the camera
let theSpan:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: HERE, longitudeDelta: HERE)

Using MKDirections to get Map Directions and Routes not working

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

How to get Location user with CLLocationManager in swift?

I have this code on my view controller but this not working:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
var location: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
location=CLLocationManager()
location.delegate = self
location.desiredAccuracy=kCLLocationAccuracyBest
location.startUpdatingLocation()
}
func locationManager(location:CLLocationManager, didUpdateLocations locations:AnyObject[]) {
println("locations = \(locations)")
label1.text = "success"
}
I have the permissions how I read in other post. but I don't obtain never, no println..
Thanks!!
first add this two line in plist file
1) NSLocationWhenInUseUsageDescription
2) NSLocationAlwaysUsageDescription
Then this is class working complete implement this
import UIKit
import CoreLocation
#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: NSDictionary?) -> Bool {
initLocationManager();
return true
}
// Location Manager helper stuff
func initLocationManager() {
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.locationServicesEnabled
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
}
// Location Manager Delegate stuff
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationManager.stopUpdatingLocation()
if (error) {
if (seenError == false) {
seenError = true
print(error)
}
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: AnyObject[]!) {
if (locationFixAchieved == false) {
locationFixAchieved = true
var locationArray = locations as NSArray
var locationObj = locationArray.lastObject as CLLocation
var coord = locationObj.coordinate
println(coord.latitude)
println(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 to location Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
if (shouldIAllow == true) {
NSLog("Location to Allowed")
// Start location services
locationManager.startUpdatingLocation()
} else {
NSLog("Denied access: \(locationStatus)")
}
}
}
Following are the simple steps for getting user location in Swift 3
1) First add this line in plist file with description
NSLocationWhenInUseUsageDescription
2) Add CoreLocation.framework in your project(Under section Build Phases-> Link Binary With Library)
3) In AppDelegate class
import CoreLocation
4) Create locationManager Object as follows
var locationManager:CLLocationManager!
5) Write following code in didFinishLaunchingWithOptions
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = 200
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
6) Confirm CLLocationManagerDelegate delegate like as follows
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate
7) Write CLLocationManagerDelegate delegate method for getting user location
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("location error is = \(error.localizedDescription)")
}
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = (manager.location?.coordinate)!
print("Current Locations = \(locValue.latitude) \(locValue.longitude)")
}
Since you're declaring location as an explicitly unwrapped optional (CLLocationManager!) it requires an initializer, either in an init method as suggested by jhurray, or just inline, as:
var location: CLLocationManager! = nil
Note that you've got other possible problems as well, including that iOS 8 has new requirements for querying the user for permission to use CoreLocation. See this question for more information.
This is the same code as above but cleaned up to work with Swift as of the date of this posting. This worked for me.
Kudos to the original poster.
(note, stick this into whatever class you will use to handle your location stuff.)
var lastLocation = CLLocation()
var locationAuthorizationStatus:CLAuthorizationStatus!
var window: UIWindow?
var locationManager: CLLocationManager!
var seenError : Bool = false
var locationFixAchieved : Bool = false
var locationStatus : NSString = "Not Started"
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.initLocationManager()
}
// Location Manager helper stuff
func initLocationManager() {
seenError = false
locationFixAchieved = false
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
}
// Location Manager Delegate stuff
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationManager.stopUpdatingLocation()
if ((error) != nil) {
if (seenError == false) {
seenError = true
print(error)
}
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
if (locationFixAchieved == false) {
locationFixAchieved = true
var locationArray = locations as NSArray
var locationObj = locationArray.lastObject as CLLocation
var coord = locationObj.coordinate
println(coord.latitude)
println(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 to location Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
if (shouldIAllow == true) {
NSLog("Location to Allowed")
// Start location services
locationManager.startUpdatingLocation()
} else {
NSLog("Denied access: \(locationStatus)")
}
}
Do following stuff in viewcontroller [Using swift] -
class ViewController:
UIViewController,MKMapViewDelegate,CLLocationManagerDelegate {
var locationManager: CLLocationManager?
var usersCurrentLocation:CLLocationCoordinate2D?
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager = CLLocationManager()
if CLLocationManager.authorizationStatus() == .NotDetermined{
locationManager?.requestAlwaysAuthorization()
}
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.distanceFilter = 200
locationManager?.delegate = self
startUpdatingLocation()
usersCurrentLocation = CLLocationCoordinate2DMake(LATTITUDE, LONGITUDE)
let span = MKCoordinateSpanMake(0.005, 0.005)
let region = MKCoordinateRegionMake(usersCurrentLocation!, span)
mapview.setRegion(region, animated: true)
mapview.delegate = self
mapview.showsUserLocation = true
}
//MARK: CLLocationManagerDelegate methods
func startUpdatingLocation() {
self.locationManager?.startUpdatingLocation()
}
func stopUpdatingLocation() {
self.locationManager?.stopUpdatingLocation()
}
// MARK: MKMapViewDelegate
func mapView(mapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation){
mapview.centerCoordinate = userLocation.location!.coordinate
mapview.showsUserLocation = true
regionWithGeofencing()
}
You need to have init functions.
Override init(coder:) and init(nibName: bundle:) and add any custom init you want.
Because you have said that location is not optional, you must initialize it before your super init calls in ALL of your init functions.
func init() {
...
location = CLLocationManager()
// either set delegate and other stuff here or in viewDidLoad
super.init(nibName:nil, bundle:nil)
// other initialization below
}
It should be written as
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

Resources