CLLocationManager didUpdateLocations pas être appelé
Je suis dans le processus d'apprentissage d'iOS 8 développement d'une application avec Swift. J'ai suivi un tutoriel sur la Cabane dans les arbres qui vous guide à travers la construction d'une application météo rapide et iOS 8.
Comme une amélioration de l'application, l'auteur/tuteur suggère d'utiliser CLLocationManager
pour obtenir l'emplacement de l'appareil à alimenter le temps de l'API au lieu de le codé en dur valeurs de latitude et longitude.
Donc après avoir lu divers tutoriel en ligne, je suis allé de l'avant et a tenté de mettre en œuvre cette amélioration proposée.
J'ai mis le code de la responsabilité d'obtenir les coordonnées de l'emplacement à l'intérieur de la AppDelegate.swift
fichier.
AppDelegate.Code swift
import UIKit
import CoreLocation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var locationManager: CLLocationManager!
var errorOccured: Bool = false
var foundLocation: Bool = false
var locationStatus: NSString = "Not Started"
var location: CLLocationCoordinate2D?
var locationName: String?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//Override point for customization after application launch.
application.setStatusBarHidden(true, withAnimation: .None)
initializeLocationManager()
return true
}
func initializeLocationManager() {
self.locationManager = CLLocationManager()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
self.locationManager.requestAlwaysAuthorization()
self.locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
println("didUpdateLocations running")
if (foundLocation == false) {
self.locationManager.stopUpdatingLocation()
foundLocation = true
var locationArray = locations as NSArray
var locationObj = locationArray.lastObject as CLLocation
var geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(locationObj, completionHandler: { (placemarks, error) -> Void in
var p = placemarks as NSArray
var placemark: CLPlacemark? = p.lastObject as? CLPlacemark
self.locationName = placemark?.name
})
self.location = locationObj.coordinate
}
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationManager.stopUpdatingLocation()
if ((error) != nil) {
if (errorOccured == false) {
errorOccured = true
print(error)
}
}
}
//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)")
}
}
}
Et puis dans mon ViewController.swift
fichier que je veux obtenir les coordonnées de l'emplacement. Voici le code:
ViewController.Code swift
func getCurrentWeatherData() -> Void {
let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")
var forecastURL: NSURL
var locName = "London"
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
appDelegate.foundLocation = false
if let loc = appDelegate.location {
println("Got Location!") //for debug purposes
var currentLat = loc.latitude
var currentLng = loc.longitude
forecastURL = NSURL(string: "\(currentLat),\(currentLng)", relativeToURL: baseURL)
locName = appDelegate.locationName!
} else {
println("No Location :(") //for debug purposes
var currentLat = "51.513445"
var currentLng = "-0.157828"
forecastURL = NSURL(string: "\(currentLat),\(currentLng)", relativeToURL: baseURL)
}
let sharedSession = NSURLSession.sharedSession()
let downloadTask: NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL, completionHandler: { (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in
var urlContents = NSString.stringWithContentsOfURL(location, encoding: NSUTF8StringEncoding, error: nil)
if (error == nil) {
let dataObject = NSData(contentsOfURL: location)
let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject, options: nil, error: nil) as NSDictionary
let currentWeather = Current(weatherDictionary: weatherDictionary)
dispatch_async(dispatch_get_main_queue(), {
() -> Void in
self.locationNameLabel.text = "\(locName)"
self.temperatureLabel.text = "\(currentWeather.temperature)"
self.iconView.image = currentWeather.icon!
self.currentTimeLabel.text = "At \(currentWeather.currentTime!) it is"
self.humidityLabel.text = "\(currentWeather.humidity)"
self.percipitationLabel.text = "\(currentWeather.percipProbability)"
self.summaryLabel.text = "\(currentWeather.summary)"
//Stop refresh animation
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
} else {
let networkIssueController = UIAlertController(title: "Error", message: "Unable to load data. Connectivity error!", preferredStyle: .Alert)
let okButton = UIAlertAction(title: "OK", style: .Default, handler: nil)
networkIssueController.addAction(okButton)
let cancelButton = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
networkIssueController.addAction(cancelButton)
self.presentViewController(networkIssueController, animated: true, completion: nil)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.refreshActivityIndicator.stopAnimating()
self.refreshActivityIndicator.hidden = true
self.refreshButton.hidden = false
})
}
})
downloadTask.resume()
}
Ci-dessus est pas de travail. Mon didUpdateLocations
délégué n'est jamais appelé. Et dans la console de débogage/sortie j'ai toujours No Location :(
imprimé, ce qui suggère un échec dans l'obtention de l'emplacement, plus spécifiquement ce qui suggère que l'emplacement de la propriété sur mon AppDelegate
est nil
.
Choses que j'ai fait pour remédier à ceci:
- Dans l'info.plist j'ai ajouté les deux touches
NSLocationWhenInUseUsageDescription
etNSLocationAlwaysUsageDescription
- Assuré que je suis connecté en WiFi et pas en Ethernet
Et d'innombrables autres code des réglages, et toujours rien.
hmm pas entendu celui-ci avant, que voulez-vous dire par retenus? C'est juste une
var
en haut du fichier, comme vous pouvez le voir.Est-il en demander l'autorisation à la lecture de l'emplacement?
Oui, dans le Simulateur iOS il demande à l'utilisation des autorisations.
Désolé pour demander trivial questions, mais: avez-vous essayé sur un périphérique réel? Avez-vous mis un emplacement dans le simulateur? avez-vous essayé de réinitialiser le simulateur?
OriginalL'auteur J86 | 2014-10-05
Vous devez vous connecter pour publier un commentaire.
Quelques observations:
Comme vous le soulignez, si vous allez appeler
requestAlwaysAuthorization
, alors vous devez définirNSLocationAlwaysUsageDescription
. Si vous avez appelérequestWhenInUseAuthorization
, vous auriez besoin deNSLocationWhenInUseUsageDescription
. (Le fait que vous voyez la boîte de dialogue de confirmation signifie que vous avez fait cela correctement. Je suppose que vous voyez quel que soit la description que vous avez fournies dans la confirmation de l'alerte.)Sur votre simulateur, vous ne pouvez pas voir l'emplacement des mises à jour comme sur un appareil. Tester sur un périphérique réel.
Lorsque j'ai utilisé votre code, je vois
didUpdateLocations
quand j'ai appelé ce à partir d'un périphérique, mais pas dans le simulateur.Une fois que vous résoudre le problème de ne pas voir
didUpdateLocations
d'être appelé, il y a un autre problème:Vous êtes à la publication d'une notification lorsque l'autorisation des modifications de statut, mais pas lorsqu'un emplacement est reçu de manière asynchrone (c'est à dire plus tard). Franchement, la dernière est la plus critique de l'événement à partir de la vue du contrôleur de point de vue, donc j'aurais pensé que (a) vous devez afficher une notification lorsque l'emplacement est reçue; et (b) le point de vue du contrôleur doivent observer la présente notification. Maintenant, même si vous réussissez à obtenir
didUpdateLocations
d'être appelé, le point de vue contrôleur ne pas être informé de ces.Aussi, votre
didUpdateLocations
lance encore un autre processus asynchrone, le géocodage de les coordonner. Si votre vue contrôleur de besoins qui, aussi, vous devriez publier une notification à l'intérieur de l'achèvement du bloc de l'geocoder.Franchement, vous n'avez même pas montré le point de vue du contrôleur de code qui ajoute un observateur de ce que les notifications que ce
CLLocationManagerDelegate
code invoquer, mais je suppose que vous avez fait.OriginalL'auteur Rob
Juste pour le record: j'ai mis les deux touches (
NSLocationAlwaysUsageDescription
etNSLocationWhenInUseUsageDescription
) dans letest-plist
au lieu de laapplication-plist
..m'a fallu un certain temps pour le réaliser.....dieu, je me sens comme un idiot maintenant.
mais vous n'étiez t le premier 😉
OriginalL'auteur longilong