[英]How to get current longitude and latitude using CLLocationManager-Swift
I want to get the current longitude and latitude of a location using Swift and display them via labels.我想使用 Swift 获取某个位置的当前经度和纬度并通过标签显示它们。 I tried to do this but nothing displays on the labels.
我尝试这样做,但标签上没有显示任何内容。
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate{
@IBOutlet weak var longitude: UILabel!
@IBOutlet weak var latitude: UILabel!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
if (CLLocationManager.locationServicesEnabled()) {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
} else {
println("Location services are not enabled");
}
}
// MARK: - CoreLocation Delegate Methods
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
locationManager.stopUpdatingLocation()
removeLoadingView()
if (error) != nil {
print(error)
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var locationArray = locations as NSArray
var locationObj = locationArray.lastObject as CLLocation
var coord = locationObj.coordinate
longitude.text = coord.longitude
latitude.text = coord.latitude
longitude.text = "\(coord.longitude)"
latitude.text = "\(coord.latitude)"
}
}
IMHO, you are over complicating your code when the solution you are looking is pretty simple.恕我直言,当您正在寻找的解决方案非常简单时,您的代码过于复杂。
I have done it by using the following code:我使用以下代码完成了它:
First create an instance of CLLocationManager
and Request Authorization首先创建
CLLocationManager
的实例并请求授权
var locManager = CLLocationManager()
locManager.requestWhenInUseAuthorization()
then check if the user allowed authorization.然后检查用户是否允许授权。
var currentLocation: CLLocation!
if
CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways
{
currentLocation = locManager.location
}
to use it just do this使用它只是这样做
label1.text = "\(currentLocation.coordinate.longitude)"
label2.text = "\(currentLocation.coordinate.latitude)"
Your idea of setting them to the label.text
is correct, however the only reason I can think of is that the user is not giving you permission and that is why your current Location data will be nil.您将它们设置为
label.text
是正确的,但是我能想到的唯一原因是用户没有授予您权限,这就是您当前位置数据为零的原因。
However you would need to debug and tell us that.但是,您需要调试并告诉我们。 Also the
CLLocationManagerDelegate
is not necessary.也不需要
CLLocationManagerDelegate
。
Hopefully this helps.希望这会有所帮助。 Ask away if you have doubts.
如有疑问,请走开。
For Swift 3:对于Swift 3:
First you need to set allowance to receive User's GPS in the info.plist
.首先,您需要在
info.plist
设置允许接收用户的 GPS。
Set: NSLocationWhenInUseUsageDescription
with a random String.使用随机字符串设置:
NSLocationWhenInUseUsageDescription
。 And/or: NSLocationAlwaysUsageDescription
with a random String.和/或:带有随机字符串的
NSLocationAlwaysUsageDescription
。
Then:然后:
import UIKit
import MapKit
class ViewController: UIViewController {
var locManager = CLLocationManager()
var currentLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
locManager.requestWhenInUseAuthorization()
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways){
guard let currentLocation = locManager.location else {
return
}
print(currentLocation.coordinate.latitude)
print(currentLocation.coordinate.longitude)
}
}
}
Done.完毕。
Despite other advice you should use the CLLocationManagerDelegate
to safely retrieve a location (without using it you may get null locations when the location manager doesn't have enough time to update).尽管有其他建议,您应该使用
CLLocationManagerDelegate
来安全地检索位置(如果不使用它,当位置管理器没有足够的时间更新时,您可能会得到空位置)。 I strongly recommend wrapping the location manager code within a static shared helper (something along these lines):我强烈建议将位置管理器代码包装在一个静态共享助手中(类似这样的东西):
class Locator: NSObject, CLLocationManagerDelegate {
enum Result <T> {
case .Success(T)
case .Failure(ErrorType)
}
static let shared: Locator = Locator()
typealias Callback = (Result <Locator>) -> Void
var requests: Array <Callback> = Array <Callback>()
var location: CLLocation? { return sharedLocationManager.location }
lazy var sharedLocationManager: CLLocationManager = {
let newLocationmanager = CLLocationManager()
newLocationmanager.delegate = self
// ...
return newLocationmanager
}()
// MARK: - Authorization
class func authorize() { shared.authorize() }
func authorize() { sharedLocationManager.requestWhenInUseAuthorization() }
// MARK: - Helpers
func locate(callback: Callback) {
self.requests.append(callback)
sharedLocationManager.startUpdatingLocation()
}
func reset() {
self.requests = Array <Callback>()
sharedLocationManager.stopUpdatingLocation()
}
// MARK: - Delegate
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
for request in self.requests { request(.Failure(error)) }
self.reset()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: Array <CLLocation>) {
for request in self.requests { request(.Success(self)) }
self.reset()
}
}
Then in view did load (or anywhere else you need to get the current location) run:然后在视图中加载(或您需要获取当前位置的任何其他位置)运行:
Locator.shared.locate { result in
switch result {
case .Success(locator):
if let location = locator.location { /* ... */ }
case .Failure(error):
/* ... */
}
}
In current thread a solution was proposed without delegate but in Xcode 9.1 testing in simulator it did not work, location was nil.在当前线程中,提出了一个没有委托的解决方案,但在模拟器中的 Xcode 9.1 测试中它不起作用,位置为零。 This code worked:
此代码有效:
import UIKit
import MapKit
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
if (CLLocationManager.locationServicesEnabled())
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations.last! as CLLocation
/* you can use these values*/
let lat = location.coordinate.latitude
let long = location.coordinate.longitude
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In Swift在斯威夫特
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
//Labels outlets
@IBOutlet var localityTxtField: UITextField!
@IBOutlet var postalCodeTxtField: UITextField!
@IBOutlet var aAreaTxtField: UITextField!
@IBOutlet var countryTxtField: UITextField!
let locationManager = CLLocationManager()
//View Didload
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
//Button Location
@IBAction func findMyLocation(_ sender: AnyObject) {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
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 {
print("placemarks",placemarks!)
let pm = placemarks?[0]
self.displayLocationInfo(pm)
} else {
print("Problem with the data received from geocoder")
}
})
}
func displayLocationInfo(_ placemark: CLPlacemark?) {
if let containsPlacemark = placemark {
print("your location is:-",containsPlacemark)
//stop updating location to save battery life
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 : ""
localityTxtField.text = locality
postalCodeTxtField.text = postalCode
aAreaTxtField.text = administrativeArea
countryTxtField.text = country
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error while updating location " + error.localizedDescription)
}
}
I am junior but I solved it in this way: I have created extension of my class inherited CLLocationManagerDelegate and following steps:我是初中生,但我以这种方式解决了这个问题:我创建了继承 CLLocationManagerDelegate 的类的扩展,并执行以下步骤:
1.Import CoreLocation to your ViewController 1.将 CoreLocation 导入您的 ViewController
import CoreLocation
2.Then initialize location manager and location variables inside your ViewController. 2.然后在您的 ViewController 中初始化位置管理器和位置变量。
var locManager = CLLocationManager()
var currentUserLocation: CLLocation!
Inside viewDidLoad() request location init delegate and requestUsageDescription内部 viewDidLoad() 请求位置初始化委托和 requestUsageDescription
locManager.requestWhenInUseAuthorization() locManager.delegate = self locManager.requestLocation()
Then I have just created extension for my viewController inheriting CLLocationManagerDelegate然后我刚刚为我的 viewController 创建了继承 CLLocationManagerDelegate 的扩展
extension theNameOfYourViewController: CLLocationManagerDelegate{ func locationManager(_ manager: CLLocationManager, didFailWithError error: Swift.Error) { print(error) } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { // .requestLocation will only pass one location to the locations array // hence we can access it by taking the first element of the array if let location = locations.first { print(location.coordinate.latitude) print(location.coordinate.longitude) } } }
Just remember to change the names according your needs also whenever you need location just use the function request location只要记住根据您的需要更改名称,只要您需要位置,只需使用功能请求位置
locManager.requestLocation()
I agree with Kevin above, but if you're looking for less code for something simpler the following will suffice: Make sure to use the CLLocationManagerDelegate
我同意上面的凯文,但如果你正在寻找更少的代码来做更简单的事情,以下就足够了:确保使用
CLLocationManagerDelegate
Swift 4:斯威夫特 4:
In viewDidLoad you can add the following在 viewDidLoad 中,您可以添加以下内容
locationManager.requestWhenInUseAuthorization()
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse) || (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways) {
currentLocation = locationManager.location
print(currentLocation.coordinate.latitude)
print(currentLocation.coordinate.longitude)
}
}
And for the first request respond once the user gives or denies permission:一旦用户给予或拒绝许可,对于第一个请求响应:
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.requestLocation()
currentLocation = locationManager.location
print(currentLocation.coordinate.latitude)
print(currentLocation.coordinate.longitude)
//Process location information and update.
}
Make sure to add the following keys to Info.plist:确保将以下键添加到 Info.plist:
Privacy - Location When In Use Usage Description Privacy - Location Always and When In Use Usage Description隐私 - 使用时的位置 使用说明 隐私 - 始终和使用时的位置 使用说明
Create User class:创建用户类:
import Foundation
import CoreLocation
import MapKit
class User: NSObject, ObservableObject {
@Published var position = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
let manager = CLLocationManager()
override init() {
super.init()
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.requestLocation()
}
}
extension User: CLLocationManagerDelegate {
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
print("Location services authorization request")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("User location updated")
print("Updated position: \(locations.first?.coordinate.latitude ?? 00)")
if let location = locations.first {
self.position = location.coordinate
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Failed to find user's location: \(error.localizedDescription)")
}
}
Update更新
Swift 5+
Xcode 13+
Add these permission in info plist
在信息 plist 中添加这些权限
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs your location to show nearby services</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs your location to show nearby services</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs your location to show nearby services</string>
Import this in your view controller在您的视图控制器中导入它
import CoreLocation
in viewDidLoad()
在 viewDidLoad()
override func viewDidLoad() {
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
}
Create extension like this像这样创建扩展
extension RegisterViewController : CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("error:: \(error.localizedDescription)")
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let locationSafe = locations.last {
locationManager.stopUpdatingLocation()
let latitude = locationSafe.coordinate.latitude
let longitude = locationSafe.coordinate.longitude
self.currentLatitude = latitude
self.currentLongitude = longitude
print(" Lat \(latitude) , Longitude \(longitude)")
}
if locations.first != nil {
print("location:: \(locations[0])")
}
}
}
Run and check this运行并检查这个
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.