CLLocation Manager en Swift para obtener la ubicación del usuario

Estoy tratando de convertir una aplicación antigua en ObjC a Swift como ejercicio de práctica y me he topado con algunos problemas. De la forma en que lo tenía en la aplicación anterior, estaba estableciendo CLLocation Manager y luego usaría:

manager = [[CLLocationManager alloc]init]; manager.delegate = self; manager.desiredAccuracy = kCLLocationAccuracyBest; [manager startUpdatingLocation] 

que llamaría automáticamente:

 -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{ } 

y de allí pude extraer toda la información que necesitaba. Pero en breve, no hay autocompletado de este método y no puedo encontrar la manera de reproducirlo. La documentación dice que

 startUpdatingLocation() 

todavía será llamado por el delegado, pero no está sucediendo.

Esto es lo que tengo hasta ahora:

 import UIKit import corelocation class ViewController: UIViewController,CLLocationManagerDelegate{ @IBOutlet var gpsResult : UILabel var manager:CLLocationManager! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. manager = CLLocationManager() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyBest manager.startUpdatingLocation() } func locationManager(manager:CLLocationManager, didUpdateLocations locations:AnyObject[]) { println("locations = \(locations)") gpsResult.text = "success" } } 

Se agradecerá cualquier ayuda o punteros sobre dónde mirar. Gracias.

EDITAR: actualizado de Sugerencias, pero aún no funciona

EDIT2: Parece ser un error que no permite que el método funcione correctamente en ViewController

Te faltan dos cosas. En primer lugar, debe solicitar permiso utilizando requestAlwaysAuthorization o requestWhenInUseAuthorization() . Entonces su viewDidLoad() debería ser así:

 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. locationManager = CLLocationManager() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestAlwaysAuthorization() locationManager.startUpdatingLocation() } 

Segundo, edite su Info.plist como se indica aquí .

Primero agrega esta dos líneas en un archivo plist

1) NSLocationWhenInUseUsageDescription

2) NSLocationAlwaysUsageDescription

Entonces esta es la clase de trabajo completa implementar esto

 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 // If failed 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) } } // authorization status 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)") } } } 

No estoy seguro de por qué, pero parece que startUpdatingLocation no presenta el mensaje del usuario en el simulador de iOS 7, pero cuando lo habilité manualmente, funcionó como esperaba si utilizaba la forma más reciente del método de delegado:

 var manager:CLLocationManager! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. manager = CLLocationManager() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyBest manager.startUpdatingLocation() } func locationManager(manager:CLLocationManager, didUpdateLocations locations:[AnyObject]) { // Updated to current array syntax [AnyObject] rather than AnyObject[] println("locations = \(locations)") } 

El formato que está utilizando ha quedado obsoleto desde iOS 5 o 6, por lo que aparentemente no es compatible con las rápidas capas puente.

tenía el mismo problema didUpdateLocations – no funcionaba. Ejecuta tu aplicación. Vaya a la página Configuración -> Privacidad -> Ubicación y apague los Servicios de ubicación. didFailWithError detectará el error sobre los servicios de ubicación ausentes. Luego enciéndelo. Desde ese momento didUpdateLocations captará ubicaciones.

Espero que haya dos formas.

  var locationManager: CLLocationManager = CLLocationManager() var initialLocation :CLLocation? var updatedUserLocation :CLLocation? override func viewDidLoad() { super.viewDidLoad() { //MapView Location locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() locationManager.startUpdatingHeading() } 

Implementación de CLLocationManagerDelegate:

 //CLLocationManager Delegate func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { // This only works when user location is updated. gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel) } func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { //Error indicates GPS permission restricted gpsProviderStatusLabel.changeStatusToOff(gpsProviderStatusLabel) //Initial Location initialLocation = locations.first //Getting Updated Location updatedUserLocation = locations.last } 

Verificación de la autorización de CLLocationDelegate:

  func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) { //This method does real time status monitoring. switch status { case .NotDetermined: print(".NotDetermined") break case .AuthorizedAlways: print(".AuthorizedAlways") gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel) break case .Denied: print(".Denied") gpsProviderStatusLabel.changeStatusToOff(gpsProviderStatusLabel) break case .AuthorizedWhenInUse: print(".AuthorizedWhenInUse") gpsProviderStatusLabel.changeStatusToOn(gpsProviderStatusLabel) break case .Restricted: print(".Restricted") break default: print("Unhandled authorization status") break } } 

Nota: changeStatusToOn o changeStatusToOff es un método UILabel Extenion que activa / desactiva el texto de la etiqueta con colores verdes / rojos.

Aquí está mi código muy simple que funciona:

primero agregue el marco de Ubicación principal en Marcos generales / vinculados y bibliotecas

luego agregue los siguientes en Info.plist:

 NSLocationWhenInUseUsageDescription blablabla NSLocationAlwaysUsageDescription blablabla 

este es mi archivo ViewController.swift:

 import UIKit import CoreLocation class ViewController: UIViewController, CLLocationManagerDelegate { var locationManager:CLLocationManager! override func viewDidLoad() { super.viewDidLoad() locationManager = CLLocationManager() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestAlwaysAuthorization() locationManager.startUpdatingLocation() } func locationManager(manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) { print("locations = \(locations)") } } 

Para Swift 3

 import UIKit import CoreLocation class ViewController: UIViewController,CLLocationManagerDelegate { var locationManager:CLLocationManager! override func viewDidLoad() { super.viewDidLoad() locationManager = CLLocationManager() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestAlwaysAuthorization() locationManager.startUpdatingLocation() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func locationManager(_ manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) { print("locations = \(locations)") } } 

no olvide agregar NSLocationWhenInUseUsageDescription o NSLocationAlwaysUsageDescription en su archivo de configuración (target / Info / custom target properties)

Agregue la propiedad de abajo 2 en info.plist

 NSLocationWhenInUseUsageDescription : Location information is used for fraud prevention Privacy - Location Usage Description : Location information is used for fraud prevention 

Si desea obtener la ubicación del usuario actualizada de manera predeterminada, sin hacer clic en “Simular ubicación” cada vez, vaya a

 YourProject-->Build Phases-->Link Binary with libraries-->Add corelocation.framework 

La ubicación se actualiza automáticamente / de forma predeterminada cuando ejecuta la aplicación en el simulador. ¡Probado y funciona en Swift 2!

Esto pedirá permiso y rastreará si se le dio permiso para abandonarlo con una alerta. Detiene el rastreo al presionar el botón Atrás.

info.plist

 NSLocationAlwaysUsageDescription Allow tracking while completing a survey 

Clase:

 import UIKit import CoreLocation class LocationViewController: BaseViewController, CLLocationManagerDelegate { // MARK: Constants private static let enableLocationServices = [ "title" : "Location", "message" : "Enable location services", "buttonTitle" : "OK" ] // MARK: Private variables private var manager: CLLocationManager? // MARK: UIViewCOntroller methods @IBAction func backButtonPressed(sender : UIButton) { stopTracking() detatchLocationManager() dismissViewControllerAnimated(true, completion: nil) } override func viewDidLoad() { super.viewDidLoad() attachLocationManager() } // Mark: Location func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) { if status == .AuthorizedAlways { manager.startUpdatingLocation() } else if status != .NotDetermined { showEnableLocationServicesAlert() } } func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { for location in locations { getDependencyService().getProject().appendLocationTrackingFile(location.timestamp, latitude: location.coordinate.latitude, longitude: location.coordinate.longitude) } } // MARK: LocationViewController private func attachLocationManager() { manager = CLLocationManager() manager?.delegate = self manager?.desiredAccuracy = kCLLocationAccuracyBest if CLLocationManager.authorizationStatus() != .AuthorizedAlways { manager?.requestAlwaysAuthorization() } else if CLLocationManager.locationServicesEnabled() { startTracking() } } private func detatchLocationManager() { manager?.stopUpdatingLocation() manager?.delegate = nil manager = nil } private func startTracking() { manager?.startUpdatingLocation() } private func stopTracking() { manager?.stopUpdatingLocation() } private func showEnableLocationServicesAlert() { getDependencyService().getUiHelper().showAlert(FrogFirstSurveyViewController.enableLocationServices, completion: { self.dismissViewControllerAnimated(true, completion: nil) }) } }