CLLocationManager didUpdateLocations没有被调用 [英] CLLocationManager didUpdateLocations not being called

查看:73
本文介绍了CLLocationManager didUpdateLocations没有被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Swift学习iOS 8应用开发。我已经按照 Treehouse 上的教程进行操作,它引导您完成在Swift和iOS 8中构建天气应用的过程。

I am in the process of learning iOS 8 app development with Swift. I have followed a tutorial on Treehouse that walks you through building a weather app in Swift and iOS 8.

作为对应用程序的改进,作者/导师建议使用 CLLocationManager 获取设备的位置以输入天气API

As an improvement to the app, the author/tutor suggests using CLLocationManager to get the location of the device to feed into the weather API instead of the hard coded latitude and longitude values.

因此,在线阅读了各种教程之后,我继续尝试实现建议的改进。

So having read various tutorial online, I have gone ahead and attempted to implement this suggested improvement.

我已将负责获取位置坐标的代码放在 AppDelegate.swift 文件中。

I have placed the code responsible for getting the location coordinates inside the AppDelegate.swift file.

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

}

然后在我的 ViewController中.swift 文件我要获取位置坐标。这是代码:

And then in my ViewController.swift file I want to obtain the location coordinates. Here is the code:

ViewController.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()
}

The以上是不起作用。我的 didUpdateLocations 委托从未被调用。在调试控制台/输出中,我总是打印出 No Location:(,这表明获取位置失败,更具体地说,这表明我的 AppDelegate nil

The above is not working. My didUpdateLocations delegate never gets called. And in the debug console/output I always get No Location :( printed out, suggesting a failure in getting the location, more specifically suggesting that the location property on my AppDelegate is nil.

我为解决此问题所做的事情:

Things I have done to remedy this:


  1. 在info.plist中,我添加了两个键 NSLocationWhenInUseUsageDescription NSLocationAlwaysUsageDescription

  2. 确保我通过WiFi而不是以太网连接


$

推荐答案

一些观察结果:


  1. 正如您所指出的,如果您要呼叫 requestAlwaysAuthorization ,那么您必须设置 NSLocationAlwaysUsageDescription 。如果调用了 requestWhenInUseAuthorization ,则需要 NSLocationWhenInUseUsageDescription 。(事实是您会看到确认对话框,表示您已正确完成此操作。我假设您看到的是确认警报中提供的任何说明。)

  1. As you point out, if you're going to call requestAlwaysAuthorization, then you must set NSLocationAlwaysUsageDescription. If you called requestWhenInUseAuthorization, you'd need NSLocationWhenInUseUsageDescription. (The fact that you see the confirmation dialog means that you've done this correctly. I assume you are seeing whatever description you supplied in the confirmation alert.)

在模拟器上,您可能看不到设备上的位置更新。在实际设备上进行测试。

On your simulator, you may not see location updates like on a device. Test this on an actual device.

当我使用您的代码时,当我从设备而不是从模拟器调用此代码时,会看到 didUpdateLocations

When I used your code, I see didUpdateLocations when I called this from a device, but not from the simulator.

解决了看不到被调用的 didUpdateLocations 的问题之后,还有另一个问题:

Once you solve the issue of not seeing didUpdateLocations being called, there is another issue:

您将在授权状态更改时发布通知,但在异步接收位置(即稍后)时发布通知。坦率地说,从视图控制器的角度来看,后者是更关键的事件,因此我认为(a)您应该在收到位置信息后发布通知; (b)视图控制器应遵守此通知。现在,即使您成功调用了 didUpdateLocations ,也不会通知视图控制器。

You are posting a notification when the authorization status changes, but not when a location is received asynchronously (i.e. later). Frankly, the latter is the more critical event from the view controller's perspective, so I would have thought that (a) you should post a notification when the location is received; and (b) the view controller should observe this notification. Right now, even if you succeed in getting didUpdateLocations to be called, the view controller won't be notified of such.

此外,您的 didUpdateLocations 正在启动另一个异步过程,即坐标的地址解析。如果您的视图控制器也需要它,则应该在地址解析器的完成代码块内发布通知。

Also, your didUpdateLocations is initiating yet another asynchronous process, the geocode of the coordinate. If your view controller needs that, too, you should post a notification inside the completion block of the geocoder.

坦率地说,您甚至没有向我们显示视图控制器代码这将为该 CLLocationManagerDelegate 代码将调用的任何通知添加观察者,但是我想您已经做到了。

Frankly, you haven't even shown us the view controller code that adds an observer for whatever notifications that this CLLocationManagerDelegate code will invoke, but I assume you have done that.

这篇关于CLLocationManager didUpdateLocations没有被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆