我该如何存储用户的当前位置并在地图上显示该位置?
我能够在地图上显示预定义的坐标,但我不知道如何从设备接收信息。
此外,我知道我必须将一些项添加到Plist中。我该如何做到这一点?
我该如何存储用户的当前位置并在地图上显示该位置?
我能够在地图上显示预定义的坐标,但我不知道如何从设备接收信息。
此外,我知道我必须将一些项添加到Plist中。我该如何做到这一点?
要获取用户当前位置,您需要声明:
let locationManager = CLLocationManager()
在 viewDidLoad()
方法中,你需要像这样实例化 CLLocationManager
类:
// Ask for Authorisation from the User.
self.locationManager.requestAlwaysAuthorization()
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
然后在CLLocationManagerDelegate方法中,您可以获取用户当前位置的坐标:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
print("locations = \(locValue.latitude) \(locValue.longitude)")
}
在info.plist中,您将需要添加NSLocationAlwaysUsageDescription
和您的自定义警告消息,例如:AppName(演示应用程序)想要使用您的当前位置。你应该执行以下步骤:
CoreLocation.framework
添加到BuildPhases -> Link Binary With Libraries中(自XCode 7.2.1起不再需要)CoreLocation
CLLocationManagerDelegate
NSLocationWhenInUseUsageDescription
和NSLocationAlwaysUsageDescription
添加到plist文件中初始化位置管理器:
locationManager = CLLocationManager()
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
通过以下方式获取用户位置:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue:CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locValue.latitude) \(locValue.longitude)")
}
更新支持iOS 12.2和Swift 5
您必须在plist文件中添加以下隐私权限
<key>NSLocationWhenInUseUsageDescription</key>
<string>Description</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Description</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Description</string>
这就是我目前的状况
在Swift 2.0中获取当前位置并在地图上显示
确保您已将CoreLocation和MapKit框架添加到您的项目中(在XCode 7.2.1中不需要此步骤)
import Foundation
import CoreLocation
import MapKit
class DiscoverViewController : UIViewController, CLLocationManagerDelegate {
@IBOutlet weak var map: MKMapView!
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
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.map.setRegion(region, animated: true)
}
}
这是结果屏幕
viewDidLoad
中的代码完全错误。即使已经授权,它也不必要地请求授权。而且在确定用户是否有权限之前就开始更新位置了。 - HangarRash导入类库,例如:
import CoreLocation
设置代理:
CLLocationManagerDelegate
像这样使用变量:
var locationManager:CLLocationManager!
在viewDidLoad()方法中,编写以下优美的代码:
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
if CLLocationManager.locationServicesEnabled(){
locationManager.startUpdatingLocation()
}
编写CLLocation代理方法:
//MARK: - location delegate methods
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation :CLLocation = locations[0] as CLLocation
print("user latitude = \(userLocation.coordinate.latitude)")
print("user longitude = \(userLocation.coordinate.longitude)")
self.labelLat.text = "\(userLocation.coordinate.latitude)"
self.labelLongi.text = "\(userLocation.coordinate.longitude)"
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(userLocation) { (placemarks, error) in
if (error != nil){
print("error in reverseGeocode")
}
let placemark = placemarks! as [CLPlacemark]
if placemark.count>0{
let placemark = placemarks![0]
print(placemark.locality!)
print(placemark.administrativeArea!)
print(placemark.country!)
self.labelAdd.text = "\(placemark.locality!), \(placemark.administrativeArea!), \(placemark.country!)"
}
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error \(error)")
}
现在设置访问位置的权限,因此将这些键值添加到您的info.plist文件中
<key>NSLocationAlwaysUsageDescription</key>
<string>Will you allow this app to always know your location?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Do you allow this app to know your current location?</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Do you allow this app to know your current location?</string>
100%工作正常,已测试
viewDidLoad
中的代码是错误的。即使已经授权,它也不必要地请求了授权。这会导致在主线程上调用 locationServicesEnabled()
时出现运行时警告。 - HangarRashimport MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate
var locationManager = CLLocationManager()
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation // note that locations is same as the one in the function declaration
manager.stopUpdatingLocation()
let coordinations = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude,longitude: userLocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.2,0.2)
将这两个组合起来以获取区域:
let region = MKCoordinateRegion(center: coordinations, span: span)//this basically tells your map where to look and where from what distance
mapView.setRegion(region, animated: true)
从你的按钮或其他你想要设置locationManagerDelegate为self的方式
现在允许位置被显示
指定准确度
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
mapView.showsUserLocation = true
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
@IBOutlet weak var mapView: MKMapView!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func locateMe(sender: UIBarButtonItem) {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
mapView.showsUserLocation = true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
manager.stopUpdatingLocation()
let coordinations = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude,longitude: userLocation.coordinate.longitude)
let span = MKCoordinateSpanMake(0.2,0.2)
let region = MKCoordinateRegion(center: coordinations, span: span)
mapView.setRegion(region, animated: true)
}
}
Swift 3.0
如果您不想在地图上显示用户位置,但只想将其存储在Firebase或其他地方,请按照以下步骤操作:
import MapKit
import CoreLocation
现在在您的VC上使用CLLocationManagerDelegate,并且您必须覆盖下面显示的最后三个方法。 您可以看到如何使用这些方法来获取当前用户位置的requestLocation()方法。
class MyVc: UIViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
isAuthorizedtoGetUserLocation()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
}
}
//if we have no permission to access user location, then ask user for permission.
func isAuthorizedtoGetUserLocation() {
if CLLocationManager.authorizationStatus() != .authorizedWhenInUse {
locationManager.requestWhenInUseAuthorization()
}
}
//this method will be called each time when a user change his location access preference.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
print("User allowed us to access location")
//do whatever init activities here.
}
}
//this method is called by the framework on locationManager.requestLocation();
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("Did location updates is called")
//store the user location here to firebase or somewhere
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Did location updates is called but failed getting location \(error)")
}
}
现在,当用户登录您的应用程序时,您可以编写下面的调用代码。当调用requestLocation()时,它将进一步调用上面的didUpdateLocations,并且您可以将位置存储到Firebase或任何其他地方。if CLLocationManager.locationServicesEnabled() {
locationManager.requestLocation();
}
如果您正在使用 GeoFire,则可以按照下面的方式在 didUpdateLocations 方法中存储位置。geoFire?.setLocation(locations.first, forKey: uid) where uid is the user id who logged in to the app. I think you will know how to get UID based on your app sign in implementation.
最后但并非最不重要的,进入您的Info.plist,并启用“隐私-使用时获取位置”的描述。
当您使用模拟器进行测试时,它总是会给您一个在Simulator->Debug->Location中配置的自定义位置。
locationServicesEnabled()
会导致运行时警告。如果当前状态未知,应该在didChangeAuthorization
委托方法中调用requestWhenInUseAuthorization()
。你从未调用过startUpdatingLocation
(当状态被授权时,应该在didChangeAuthorization
委托中调用)。 - HangarRash首先在您的项目中添加两个框架
1:MapKit
2:CoreLocation(自XCode 7.2.1起不再需要)
在您的类中定义
var manager:CLLocationManager!
var myLocations: [CLLocation] = []
然后在viewDidLoad方法中编写以下代码:
manager = CLLocationManager()
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
//Setup our Map View
mapobj.showsUserLocation = true
不要忘记在plist文件中添加这两个值。1: NSLocationWhenInUseUsageDescription
2: NSLocationAlwaysUsageDescription
viewDidLoad
中的代码完全错误。即使已经授权,它也会不必要地请求授权。而且在确定用户是否有权限之前,它就开始更新位置了。您从未设置委托,因此无法响应授权更改或位置更新。 - HangarRash使用方法:
在类中定义字段
let getLocation = GetLocation()
通过简单的代码在类的函数中使用:
getLocation.run {
if let location = $0 {
print("location = \(location.coordinate.latitude) \(location.coordinate.longitude)")
} else {
print("Get Location failed \(getLocation.didFailWithError)")
}
}
类别:
import CoreLocation
public class GetLocation: NSObject, CLLocationManagerDelegate {
let manager = CLLocationManager()
var locationCallback: ((CLLocation?) -> Void)!
var locationServicesEnabled = false
var didFailWithError: Error?
public func run(callback: @escaping (CLLocation?) -> Void) {
locationCallback = callback
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
manager.requestWhenInUseAuthorization()
locationServicesEnabled = CLLocationManager.locationServicesEnabled()
if locationServicesEnabled { manager.startUpdatingLocation() }
else { locationCallback(nil) }
}
public func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
locationCallback(locations.last!)
manager.stopUpdatingLocation()
}
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
didFailWithError = error
locationCallback(nil)
manager.stopUpdatingLocation()
}
deinit {
manager.stopUpdatingLocation()
}
}
不要忘记在info.plist中添加“NSLocationWhenInUseUsageDescription”
import CoreLocation
import UIKit
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status != .authorizedWhenInUse {return}
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
let locValue: CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locValue.latitude) \(locValue.longitude)")
}
}
由于对requestWhenInUseAuthorization
的调用是异步的,因此应用程序在用户授予权限或拒绝权限后调用locationManager
函数。因此,在用户授予权限时将位置获取代码放置在该函数中是适当的。这是我发现的最好的有关此问题的教程。
MapKit
库和CoreLocation
库,并在类定义中添加CLLocationManagerDelegate
。 - LukesiviNSLocationAlwaysUsageDescription
已更名为Privacy - Location Always Usage Description
。 - Saoud RizwanlocationManager
声明为全局变量,而不是在viewDidLoad
中声明为局部变量。 - chengsam