corelocation ios xcode core-location cllocationmanager

corelocation - iOS CLLocationManager en una clase separada



corelocation swift 4 (5)

Tengo varios controladores de vista que necesitan obtener la ubicación del usuario, así que quise crear una clase separada a la que los ViewControllers puedan llamar para obtener la ubicación más reciente del usuario.

locationManager: didUpdateToLocation: fromLocation devuelve void. ¿Cómo transfiero los datos de latitud y longitud a mis ViewControllers tan pronto como se calcula la latitud y longitud del usuario?

Podría intentar escribir captadores y definidores en mi clase de gestión de ubicación, pero si lo hago, ¿cómo puedo saber cuándo llamar a los métodos de captador de latitud y captador de longitud desde mi clase ViewController? ¿Cómo puedo mantener el hilo principal de ViewController para esperar los valores de latitud y longitud de la clase locationManaging?

¡Gracias!


Como dijo el usuario 1071136, un administrador de ubicación de singleton es probablemente lo que quieres. Cree una clase, una subclase de NSObject, con solo una propiedad, un CLLocationManager .

LocationManagerSingleton.h:

#import <MapKit/MapKit.h> @interface LocationManagerSingleton : NSObject <CLLocationManagerDelegate> @property (nonatomic, strong) CLLocationManager* locationManager; + (LocationManagerSingleton*)sharedSingleton; @end

LocationManagerSingleton.m:

#import "LocationManagerSingleton.h" @implementation LocationManagerSingleton @synthesize locationManager; - (id)init { self = [super init]; if(self) { self.locationManager = [CLLocationManager new]; [self.locationManager setDelegate:self]; [self.locationManager setDistanceFilter:kCLDistanceFilterNone]; [self.locationManager setHeadingFilter:kCLHeadingFilterNone]; [self.locationManager startUpdatingLocation]; //do any more customization to your location manager } return self; } + (LocationManagerSingleton*)sharedSingleton { static LocationManagerSingleton* sharedSingleton; if(!sharedSingleton) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedSingleton = [LocationManagerSingleton new]; } } return sharedSingleton; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { //handle your location updates here } - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading { //handle your heading updates here- I would suggest only handling the nth update, because they //come in fast and furious and it takes a lot of processing power to handle all of them } @end

Para obtener la ubicación recibida más recientemente, simplemente use [LocationManagerSingleton sharedSingleton].locationManager.location . Puede llevar unos segundos calentar el GPS para obtener ubicaciones precisas.


Cree una clase singleton que tenga propiedades de latitude y longitude , startLocating y endLocating . En la clase, cree una instancia de CLLocationManager y establezca su delegado para que sea el singleton. En startLocating y endLocating , llame a los métodos apropiados de la instancia de CLLocationManager . Haga que los métodos delegados actualicen las propiedades de latitude y longitude . En otros ViewControllers , lea las propiedades de latitude y longitude este singleton.

Para saber cuándo leer esas propiedades de otro ViewController , configure un observador en estas propiedades (consulte la Referencia del protocolo NSKeyValueObserving

Antes de hacer esto, busque en Internet los códigos existentes.

Después de hacer esto, cárguelo a GitHub con una licencia permisiva.


En base a las respuestas anteriores, esto es lo que hice y puede encontrar el ejemplo completo en github https://github.com/irfanlone/CLLocationManager-Singleton-Swift

Solo importa este archivo en tu proyecto, entonces puedes elegir implementar el LocationUpdateProtocol o escuchar la notificación de actualizaciones de ubicación.

import MapKit protocol LocationUpdateProtocol { func locationDidUpdateToLocation(location : CLLocation) } /// Notification on update of location. UserInfo contains CLLocation for key "location" let kLocationDidChangeNotification = "LocationDidChangeNotification" class UserLocationManager: NSObject, CLLocationManagerDelegate { static let SharedManager = UserLocationManager() private var locationManager = CLLocationManager() var currentLocation : CLLocation? var delegate : LocationUpdateProtocol! private override init () { super.init() self.locationManager.delegate = self self.locationManager.desiredAccuracy = kCLLocationAccuracyBest self.locationManager.distanceFilter = kCLLocationAccuracyHundredMeters locationManager.requestAlwaysAuthorization() self.locationManager.startUpdatingLocation() } // MARK: - CLLocationManagerDelegate func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) { currentLocation = newLocation let userInfo : NSDictionary = ["location" : currentLocation!] dispatch_async(dispatch_get_main_queue()) { () -> Void in self.delegate.locationDidUpdateToLocation(self.currentLocation!) NSNotificationCenter.defaultCenter().postNotificationName(kLocationDidChangeNotification, object: self, userInfo: userInfo as [NSObject : AnyObject]) } } }

Uso:

class ViewController: UIViewController, LocationUpdateProtocol { var currentLocation : CLLocation! override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "locationUpdateNotification:", name: kLocationDidChangeNotification, object: nil) let LocationMgr = UserLocationManager.SharedManager LocationMgr.delegate = self } // MARK: - Notifications func locationUpdateNotification(notification: NSNotification) { let userinfo = notification.userInfo self.currentLocation = userinfo!["location"] as! CLLocation print("Latitude : /(self.currentLocation.coordinate.latitude)") print("Longitude : /(self.currentLocation.coordinate.longitude)") } // MARK: - LocationUpdateProtocol func locationDidUpdateToLocation(location: CLLocation) { currentLocation = location print("Latitude : /(self.currentLocation.coordinate.latitude)") print("Longitude : /(self.currentLocation.coordinate.longitude)") } }


En el proceso de aprender a obtener la ubicación del usuario en una clase de singleton, descargué este código https://github.com/irfanlone/CLLocationManager-Singleton-Swift . Después de jugar con él para ejecutarlo en Xcode8.3.3 Swift 3, no puedo obtener ningún resultado en la consola de depuración. De hecho, ni siquiera puedo mostrar este dlalog de automatización de ubicación. Sospecho que los datos del singleton no se pasan al controlador de vista, pero no puedo encontrar la solución, ¿puede ver qué está mal? Gracias.

El código corregido para Swift 3 es:

//The singleton: import MapKit protocol LocationUpdateProtocol { func locationDidUpdateToLocation(_ location : CLLocation) } let kLocationDidChangeNotification = "LocationDidChangeNotification" class UserLocationManager: NSObject, CLLocationManagerDelegate { static let SharedManager = UserLocationManager() fileprivate var locationManager = CLLocationManager() var currentLocation : CLLocation? var delegate : LocationUpdateProtocol! fileprivate override init () { super.init() self.locationManager.delegate = self self.locationManager.desiredAccuracy = kCLLocationAccuracyBest self.locationManager.distanceFilter = kCLLocationAccuracyHundredMeters locationManager.requestAlwaysAuthorization() self.locationManager.startUpdatingLocation() } // MARK: - CLLocationManagerDelegate func locationManager(manager: CLLocationManager,didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) { currentLocation = newLocation let userInfo : NSDictionary = ["location" : currentLocation!] DispatchQueue.main.async() { () -> Void in self.delegate.locationDidUpdateToLocation(self.currentLocation!) NotificationCenter.default.post(name: Notification.Name(kLocationDidChangeNotification), object: self, userInfo: userInfo as [NSObject : AnyObject]) } } } // The ViewController import UIKit import CoreLocation class ViewController: UIViewController, LocationUpdateProtocol { var currentLocation : CLLocation! override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(ViewController.locationUpdateNotification(_:)), name: NSNotification.Name(rawValue: kLocationDidChangeNotification), object: nil) let LocationMgr = UserLocationManager.SharedManager LocationMgr.delegate = self } // MARK: - Notifications func locationUpdateNotification(_ notification: Notification) { let userinfo = notification.userInfo self.currentLocation = userinfo!["location"] as! CLLocation print("Latitude : /(self.currentLocation.coordinate.latitude)") print("Longitude : /(self.currentLocation.coordinate.longitude)") } // MARK: - LocationUpdateProtocol func locationDidUpdateToLocation(_ location: CLLocation) { currentLocation = location print("Latitude : /(self.currentLocation.coordinate.latitude)") print("Longitude : /(self.currentLocation.coordinate.longitude)") } }


Esto es lo que hice cuando implementé un administrador de ubicación singleton en swift. Se basa en la estrategia del usuario1071136, así como en este patrón veloz .

// // UserLocationManager.swift // // Use: call SharedUserLocation.currentLocation2d from any class import MapKit class UserLocation: NSObject, CLLocationManagerDelegate { var locationManager = CLLocationManager() // You can access the lat and long by calling: // currentLocation2d.latitude, etc var currentLocation2d:CLLocationCoordinate2D? class var manager: UserLocation { return SharedUserLocation } init () { super.init() if self.locationManager.respondsToSelector(Selector("requestAlwaysAuthorization")) { self.locationManager.requestWhenInUseAuthorization() } self.locationManager.delegate = self self.locationManager.desiredAccuracy = kCLLocationAccuracyBest self.locationManager.distanceFilter = 50 self.locationManager.startUpdatingLocation() } func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) { self.currentLocation2d = manager.location.coordinate } } let SharedUserLocation = UserLocation()