错误:收集用户位置时,“代表必须响应 locationManager:didUpdateLocations:”
Posted
技术标签:
【中文标题】错误:收集用户位置时,“代表必须响应 locationManager:didUpdateLocations:”【英文标题】:Error: 'Delegate must respond to locationManager:didUpdateLocations:' when collecting user location 【发布时间】:2016-06-22 13:04:48 【问题描述】:所以我想在用户点击按钮时收集用户位置,并稍后在我的应用中使用该位置。在我当前的实现中,当点击按钮时,应该提示用户允许共享位置,然后他们应该登录到应用程序(如果您想知道,可以匿名通过 Firebase),并且应该打印用户位置信息到控制台。提示有效,但是在点击允许位置按钮后,我的应用程序终止 due to uncaught exception 'NSInternalInconsistencyException'
原因是'Delegate must respond to locationManager:didUpdateLocations:'
这很奇怪,因为我的代码中确实有一个 didUpdateLocations:
函数。
我不知道发生了什么,如果有任何帮助,我们将不胜感激。我的 ViewController 代码如下,谢谢!
/*
* Copyright (c) 2016 Ahad Sheriff
*
*/
import UIKit
import Firebase
import CoreLocation
class LoginViewController: UIViewController
// MARK: Properties
var ref: FIRDatabaseReference! // 1
var userID: String = ""
var locationManager = CLLocationManager()
override func viewDidLoad()
super.viewDidLoad()
ref = FIRDatabase.database().reference() // 2
@IBAction func loginDidTouch(sender: AnyObject)
//ask user to enable location services
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled()
//collect user's location
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
locationManager.requestLocation()
locationManager.startUpdatingLocation()
let location = self.locationManager.location
var latitude: Double = location!.coordinate.latitude
var longitude: Double = location!.coordinate.longitude
print("current latitude :: \(latitude)")
print("current longitude :: \(longitude)")
//Log in to application anonymously using Firebase
FIRAuth.auth()?.signInAnonymouslyWithCompletion() (user, error) in
if let user = user
print("User is signed in with uid: ", user.uid)
self.userID = user.uid
else
print("No user is signed in.")
self.performSegueWithIdentifier("LoginToChat", sender: nil)
else
print("Unable to determine location")
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
super.prepareForSegue(segue, sender: sender)
let navVc = segue.destinationViewController as! UINavigationController // 1
let chatVc = navVc.viewControllers.first as! ChatViewController // 2
chatVc.senderId = userID // 3
chatVc.senderDisplayName = "" // 4
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!)
//--- CLGeocode to get address of current location ---//
CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: (placemarks, error)->Void in
if (error != nil)
print("Reverse geocoder failed with error" + error!.localizedDescription)
return
if placemarks!.count > 0
let pm = placemarks![0] as CLPlacemark
self.displayLocationInfo(pm)
else
print("Problem with the data received from geocoder")
)
func displayLocationInfo(placemark: CLPlacemark?)
if let containsPlacemark = placemark
//stop updating location
locationManager.stopUpdatingLocation()
let locality = (containsPlacemark.locality != nil) ? containsPlacemark.locality : ""
let postalCode = (containsPlacemark.postalCode != nil) ? containsPlacemark.postalCode : ""
let administrativeArea = (containsPlacemark.administrativeArea != nil) ? containsPlacemark.administrativeArea : ""
let country = (containsPlacemark.country != nil) ? containsPlacemark.country : ""
print(locality)
print(postalCode)
print(administrativeArea)
print(country)
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!)
print("Error while updating location " + error.localizedDescription)
【问题讨论】:
【参考方案1】:首先,明确添加您确认CLLocationManagerDelegate
:
class LoginViewController: UIViewController, CLLocationManagerDelegate
其次,为CLLocationManager
设置委托属性:
override func viewDidLoad()
super.viewDidLoad()
locationManager.delegate = self
ref = FIRDatabase.database().reference()
第三,在CLLocationManagerDelegate
doc 中,我看到与您声明的didUpdateLocations
和didFailWithError
方法不同:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
func locationManager(_ manager: CLLocationManager, didFailWithError error: NSError)
此外,您在代码中几乎没有其他问题。它们都是关于不安全的展开。您不应该在任何地方使用不安全的展开!
。这样做你正在扼杀可选哲学。另一方面,做正确的事可以极大地提高应用程序的稳定性。在loginDidTouch
函数中进行以下更正:
var latitude: Double? = location?.coordinate.latitude
var longitude: Double? = location?.coordinate.longitude
当您第一次调用此函数时,您的位置尚未确定(它将异步确定,您将在委托方法中获取位置),这就是您在使用强制展开时出现致命错误的原因。在didUpdateLocations
函数中:
if let pm = placemarks?.first
self.displayLocationInfo(pm)
这部分代码的更正比您的原始代码更短,并且可以防止您同时发生两次可能的崩溃 - 当placemarks
为 nil 和 placemarks
不是 nil,而是空数组时
【讨论】:
谢谢,但是当我添加您建议的更改并运行应用程序时,我收到了fatal error: unexpectedly found nil while unwrapping an Optional value
另外,如果在设置 locationManager.delegate = self 之前调用 locationManager.requestLocation(),也会出现此错误。以上是关于错误:收集用户位置时,“代表必须响应 locationManager:didUpdateLocations:”的主要内容,如果未能解决你的问题,请参考以下文章
使用空数组添加新用户记录时出现“E11000 重复键错误收集”