我想使用位置数据制作一个简单的iOS应用程序。不幸的是,在设备和模拟器上进行测试时,即使我在模拟器上输入“当前位置”调试代码,我也会收到'nil'。 这是我第一次在swift 3上使用CoreLocation,所以我使用了与之前相同的方法。
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
@IBOutlet weak var latitudeLabel: UILabel!
@IBOutlet weak var longitudeLabel: UILabel!
var locationManager:CLLocationManager?
var currentLocation:CLLocation?
override func viewDidLoad() {
super.viewDidLoad()
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
updateLabels()
// Do any additional setup after loading the view, typically from a nib.
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
self.currentLocation = locations[0]
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
func updateLabels() {
latitudeLabel.text = String(describing: currentLocation?.coordinate.latitude)
longitudeLabel.text = String(describing: currentLocation?.coordinate.longitude)
print(currentLocation)
}
}
当然,我已经在Info.plist中写了所有必要的隐私密钥。
当我尝试打印currentLocation时,我收到了nil。 在最后一次发射时,我发现了这样的问题,而不是出现警报,但立即消失了
答案 0 :(得分:4)
在viewDidLoad
中,您将CLLocationManager
保存在本地变量中,但从不将其保存到您的媒体资源中。因此,它超出范围并被取消分配,可能永远不会调用您的委托方法。
直接更新您的媒体资源,或者在配置完您的位置管理员后,请务必执行self.locationManager = locationManager
。我可能会直接更新它:
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.requestAlwaysAuthorization()
locationManager?.startUpdatingLocation()
// updateLabels()
}
然后,正如rmaddy指出的那样,更新didUpdateLocations
中的标签:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last, location.horizontalAccuracy >= 0 else { return }
currentLocation = location
updateLabels()
}
答案 1 :(得分:1)
您正在从错误的地方拨打updateLabels
。您需要从locationManager(_:didUpdateLocations)
方法中调用它。由于可以在后台线程上调用该委托方法,因此请确保在使用updateLabels
时将调用包装到DispatchQueue.main.async
。