J'essaie de convertir une vieille application d'ObjC en Swift en tant qu'exercice pratique et j'ai rencontré quelques problèmes. Comme je l'avais dans l'ancienne application, cela créait le gestionnaire de CLLocation, puis j'utilisais:
manager = [[CLLocationManager alloc]init];
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyBest;
[manager startUpdatingLocation]
qui appellerait automatiquement:
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
}
et à partir de là, je pourrais extraire toutes les informations dont j'avais besoin. Mais dans Swift, il n'y a pas d'auto-complétion de cette méthode et je ne peux pas comprendre comment la reproduire. La documentation dit que
startUpdatingLocation()
sera toujours appelé par le délégué, mais cela ne se produit pas.
C'est ce que j'ai jusqu'ici:
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"
}
}
Toute aide ou indication sur les endroits où chercher serait appréciée. Merci.
EDIT: mis à jour à partir de suggestions, mais ne fonctionne toujours pas
EDIT2: Il semble y avoir un bogue empêchant la méthode de fonctionner correctement dans ViewController
Il te manque deux choses. Tout d'abord, vous devez demander l'autorisation en utilisant requestAlwaysAuthorization
ou requestWhenInUseAuthorization()
. Donc, votre viewDidLoad()
devrait être comme ceci:
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()
}
Deuxièmement, éditez votre Info.plist
comme indiqué ici .
Ajoutez d'abord ces deux lignes dans le fichier plist
1) NSLocationWhenInUseUsageDescription
2) NSLocationAlwaysUsageDescription
Ensuite, ceci est un travail de classe complet
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)")
}
}
}
Je ne sais pas pourquoi, mais il semble que startUpdatingLocation
ne présente pas l'invite de l'utilisateur sur le simulateur iOS 7, mais lorsque je l'ai activée manuellement, cela fonctionnait comme prévu si j'utilisais le nouveau formulaire de la méthode déléguée:
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)")
}
Le format que vous utilisez est obsolète depuis iOS 5 ou 6, donc apparemment, il n'est pas pris en charge du tout par les couches de pontage Swift.
avait le même problème. didUpdateLocations - ne fonctionnait pas. Exécutez votre application. Accédez à la page Paramètres -> Confidentialité -> Localisation et désactivez les services de localisation. didFailWithError intercepte l'erreur concernant les services de localisation absents. Puis allumez-le. Depuis ce moment, didUpdateLocations capturera des emplacements.
J'espère qu'il y a deux façons.
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()
}
Implémentation 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
}
Vérification de l'autorisation 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
}
}
Remarque: changeStatusToOn ou changeStatusToOff est une méthode d’extension UILabel qui rend le texte de l’étiquette activé/désactivé avec des couleurs vert/rouge.
Pour 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)")
}
}
Voici mon code très simple qui fonctionne:
ajoutez d'abord le cadre d'emplacement principal dans les cadres et bibliothèques généraux/liés
puis ajoutez ce qui suit dans Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>blablabla</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>blablabla</string>
voici mon fichier 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)")
}
}
n'oubliez pas d'ajouter NSLocationWhenInUseUsageDescription ou NSLocationAlwaysUsageDescription dans votre fichier de configuration (cible/Info/propriétés de cible iOS personnalisées
Rapide:
Ajouter la suite dans
import CoreLocation
class YourViewController: UIViewController
{
var locationManager:CLLocationManager!
}
//MARK:- Location Manager
extension YourViewController: CLLocationManagerDelegate {
func stratLocationManager()
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.checkUsersLocationServicesAuthorization()
locationManager.startUpdatingLocation()
}
func checkUsersLocationServicesAuthorization(){
/// Check if user has authorized Total Plus to use Location Services
if CLLocationManager.locationServicesEnabled()
{
switch CLLocationManager.authorizationStatus()
{
case .notDetermined:
// Request when-in-use authorization initially
// This is the first and the ONLY time you will be able to ask the user for permission
self.locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
break
case .restricted, .denied:
// Disable location features
PrintLogs("Location Access Not Available")
break
case .authorizedWhenInUse, .authorizedAlways:
// Enable features that require location services here.
PrintLogs("Location Access Available")
break
}
}
}
func locationManager(_ manager:CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("locations = \(locations)")
}
}
Cela demandera la permission et suivra si une permission est donnée sinon quitter avec une alerte. Arrête le suivi en appuyant sur le bouton de retour.
info.plist
<key>NSLocationAlwaysUsageDescription</key>
<string>Allow tracking while completing a survey</string>
Classe:
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)
})
}
}
Si vous souhaitez que l'emplacement de l'utilisateur soit mis à jour par défaut, sans cliquer sur "Simuler l'emplacement" à chaque fois, accédez à
YourProject-->Build Phases-->Link Binary with libraries-->Add corelocation.framework
L'emplacement est mis à jour automatiquement/par défaut lorsque vous exécutez l'application dans le simulateur. Testé et fonctionne dans Swift 2!
Ajouter ci-dessous 2 biens dans info.plist
NSLocationWhenInUseUsageDescription : Location information is used for fraud prevention
Privacy - Location Usage Description : Location information is used for fraud prevention