如何使用 CLLocationManager-Swift 获取当前的经度和纬度
Posted
技术标签:
【中文标题】如何使用 CLLocationManager-Swift 获取当前的经度和纬度【英文标题】:How to get current longitude and latitude using CLLocationManager-Swift 【发布时间】:2014-11-04 17:44:26 【问题描述】:我想使用 Swift 获取某个位置的当前经度和纬度,并通过标签显示它们。我尝试这样做,但标签上没有显示任何内容。
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)"
【问题讨论】:
CLLocation Manager in Swift to get Location of User 的可能重复项 【参考方案1】:恕我直言,当您正在寻找的解决方案非常简单时,您的代码过于复杂了。
我已经使用以下代码完成了:
首先创建CLLocationManager
的实例并请求授权
var locManager = CLLocationManager()
locManager.requestWhenInUseAuthorization()
然后检查用户是否允许授权。
var currentLocation: CLLocation!
if
CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways
currentLocation = locManager.location
要使用它,只需这样做
label1.text = "\(currentLocation.coordinate.longitude)"
label2.text = "\(currentLocation.coordinate.latitude)"
您将它们设置为label.text
的想法是正确的,但是我能想到的唯一原因是用户没有授予您权限,这就是您当前的位置数据将为零的原因。
但是,您需要调试并告诉我们。
CLLocationManagerDelegate
也不是必需的。
希望这会有所帮助。如果您有任何疑问,请随时询问。
【讨论】:
你的第二个代码块应该去哪里?在委托方法中? 我通常把它放在“viewdidload”或“awakefromnib”中,但它可以在任何地方使用。只要询问用户使用其位置的权限并且他/她授予它,它就没有限制。 我不同意这个建议。上面的代码甚至没有启动位置管理器——它只是确保它被授权。位置管理员的当前位置读数可能是旧的并且非常不准确。当您激活位置管理器并要求更新位置时,前几个位置结果往往非常糟糕。您确实需要设置一个代表,开始位置更新,并检查您获得的位置更新的准确度读数,直到它们安定下来。 @DuncanC 就这样吧。尊重您的意见,此代码对我有用,我将它用于我为客户创建的应用程序的生产中。更直接地说,OP 要求“使用 Swift 获取位置的当前经纬度”。因为显然这对他不起作用。这显然使它起作用,就像对我一样,从而回答了他的问题。如果你想谈谈 LocationManager 的准确性,我的朋友本身就是另一个话题。 在 xcode 9.1 中测试时对我不起作用,在模拟器中,没有委托位置为零。【参考方案2】:对于 Swift 3:
首先您需要在info.plist
中设置接收用户 GPS 的限额。
使用随机字符串设置:NSLocationWhenInUseUsageDescription
。
和/或:NSLocationAlwaysUsageDescription
带有随机字符串。
然后:
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)
完成。
【讨论】:
这段代码在“print(currentLocation.coordinate.latitude)”行给我错误 @BijenderSinghShekhawat 是的。请告诉我什么错误。怎么样? @MicroR,是的。 它使用相同的传感器 @DavidSeek 对我来说,它总是在保护声明它返回。你能帮我解决这个问题吗?【参考方案3】:尽管有其他建议,您应该使用CLLocationManagerDelegate
来安全地检索位置(不使用它,当位置管理器没有足够的时间更新时,您可能会得到空位置)。我强烈建议将位置管理器代码包装在静态共享帮助程序中(类似这些行):
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()
然后在视图中确实加载(或您需要获取当前位置的任何其他地方)运行:
Locator.shared.locate result in
switch result
case .Success(locator):
if let location = locator.location /* ... */
case .Failure(error):
/* ... */
【讨论】:
我收到一个错误:“不允许嵌套在类型 'Locator' 中的通用类型 'Result'”。我从未在 Swift 中看到过这个错误。有关修复的任何建议? @ClayEllis 在课堂外做枚举结果声明,它会起作用。 按照指令使用,出现错误,例如:使用未解析的标识符“定位器”。进入 UIViewController。 不适用于 Swift 4 和 Xcode 10,请检查一次并编辑您的答案。 尝试在定位器和错误之前添加 let。我希望它有所帮助。 Locator.shared.locate (result) in switch result case .success(let locator): break case .failure(let err): break 【参考方案4】:在当前线程中,提出了一个没有委托的解决方案,但在 Xcode 9.1 模拟器中的测试中它不起作用,位置为零。此代码有效:
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.
【讨论】:
【参考方案5】:在 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)
【讨论】:
【参考方案6】:我是初级但我以这种方式解决了它: 我创建了继承 CLLocationManagerDelegate 的类的扩展并执行以下步骤:
1.将 CoreLocation 导入到您的 ViewController
import CoreLocation
2.然后在 ViewController 中初始化位置管理器和位置变量。
var locManager = CLLocationManager()
var currentUserLocation: CLLocation!
viewDidLoad() 内部请求位置初始化委托和 requestUsageDescription
locManager.requestWhenInUseAuthorization()
locManager.delegate = self
locManager.requestLocation()
然后我刚刚为继承 CLLocationManagerDelegate 的 viewController 创建了扩展
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)
只要记住在需要位置时根据您的需要更改名称,只需使用功能请求位置
locManager.requestLocation()
【讨论】:
【参考方案7】:我同意上述 Kevin 的观点,但如果您正在寻找更简单的代码,那么以下内容就足够了:
确保使用CLLocationManagerDelegate
斯威夫特 4:
在 viewDidLoad 中可以添加以下内容
locationManager.requestWhenInUseAuthorization()
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse) || (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways)
currentLocation = locationManager.location
print(currentLocation.coordinate.latitude)
print(currentLocation.coordinate.longitude)
一旦用户给予或拒绝许可,第一个请求就会响应:
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.
【讨论】:
【参考方案8】:确保将以下键添加到 Info.plist:
隐私 - 使用时的位置 使用说明 隐私 - 始终定位和使用时使用说明
创建用户类:
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)")
【讨论】:
【参考方案9】:更新
Swift 5+
Xcode 13+
在信息列表中添加这些权限
<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 CoreLocation
在 viewDidLoad() 中
override func viewDidLoad()
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
像这样创建扩展程序
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])")
运行并检查
【讨论】:
以上是关于如何使用 CLLocationManager-Swift 获取当前的经度和纬度的主要内容,如果未能解决你的问题,请参考以下文章
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]
如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?