如何存储用户的当前位置,并在地图上显示该位置?
我可以在地图上显示预定义的坐标,只是不知道如何从设备接收信息。
我也知道我必须添加一些项目到Plist。我该怎么做呢?
如何存储用户的当前位置,并在地图上显示该位置?
我可以在地图上显示预定义的坐标,只是不知道如何从设备接收信息。
我也知道我必须添加一些项目到Plist。我该怎么做呢?
当前回答
之前所有的答案都没有正确地遵循正确的步骤。当设置CLLocationManager时,您不需要最初调用CLLocationManager. locationservicesenabled()或locationManager.requestWhenInUseAuthorization()。你不应该调用startUpdatingLocation(),直到你已经验证你有授权。
要开始,如果还没有完成,请添加所需的隐私设置。选择你的应用目标,然后转到信息选项卡。在“自定义iOS目标属性”部分右键单击并选择“添加行”。向下滚动到“隐私”条目,并选择其中之一:
"隐私-使用时的位置使用说明" "隐私-位置始终使用说明" 隐私-使用时的位置使用说明
这取决于你的应用程序的需求。对于这个值,确保你输入了一个句子,向用户解释为什么你的应用程序需要访问他们的位置。如果所提供的描述对用户没有用处,你的应用可能会被苹果拒绝。
然后使用以下(大量注释)代码作为示例,在视图控制器中获取用户的位置:
import UIKit
import CoreLocation
class ViewController: UIViewController {
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
// Setup the location manager
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation // Or other desired accuracy
// That's it for the initial setup. Everything else is handled in the
// locationManagerDidChangeAuthorization delegate method.
}
}
extension ViewController: CLLocationManagerDelegate {
// This is called as soon as the location manager is setup (in viewDidLoad)
// This is called when the user responds to the privacy dialog
// This is called if the user changes the privacy setting in the Settings app
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .notDetermined:
// Request the appropriate authorization based on the needs of the app
manager.requestWhenInUseAuthorization()
// manager.requestAlwaysAuthorization()
case .restricted:
print("Sorry, restricted")
// Optional: Offer to take user to app's settings screen
case .denied:
print("Sorry, denied")
// Optional: Offer to take user to app's settings screen
case .authorizedAlways, .authorizedWhenInUse:
// The app has permission so start getting location updates
manager.startUpdatingLocation()
@unknown default:
print("Unknown status")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("Received \(locations.count) locations")
// Some location updates can be invalid or have insufficient accuracy.
// Find the first location that has sufficient horizontal accuracy.
// If the manager's desiredAccuracy is one of kCLLocationAccuracyNearestTenMeters,
// kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer, or kCLLocationAccuracyThreeKilometers
// then you can use $0.horizontalAccuracy <= manager.desiredAccuracy. Otherwise enter the number of meters desired.
if let location = locations.first(where: { $0.horizontalAccuracy <= 40 }) {
print("Good location found: \(location)")
// Call the following if you don't need any more updates
manager.stopUpdatingLocation()
// Do something useful with the found location
// - show on a map
// - Reverse geocode to get the address
// - send to server
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Location manager error: \(error)")
}
}
其他回答
import Foundation
import CoreLocation
enum Result<T> {
case success(T)
case failure(Error)
}
final class LocationService: NSObject {
private let manager: CLLocationManager
init(manager: CLLocationManager = .init()) {
self.manager = manager
super.init()
manager.delegate = self
}
var newLocation: ((Result<CLLocation>) -> Void)?
var didChangeStatus: ((Bool) -> Void)?
var status: CLAuthorizationStatus {
return CLLocationManager.authorizationStatus()
}
func requestLocationAuthorization() {
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
manager.startUpdatingLocation()
//locationManager.startUpdatingHeading()
}
}
func getLocation() {
manager.requestLocation()
}
deinit {
manager.stopUpdatingLocation()
}
}
extension LocationService: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
newLocation?(.failure(error))
manager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.sorted(by: {$0.timestamp > $1.timestamp}).first {
newLocation?(.success(location))
}
manager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .notDetermined, .restricted, .denied:
didChangeStatus?(false)
default:
didChangeStatus?(true)
}
}
}
需要在所需的ViewController中编写此代码。
//NOTE:: Add permission in info.plist::: NSLocationWhenInUseUsageDescription
let locationService = LocationService()
@IBAction func action_AllowButtonTapped(_ sender: Any) {
didTapAllow()
}
func didTapAllow() {
locationService.requestLocationAuthorization()
}
func getCurrentLocationCoordinates(){
locationService.newLocation = {result in
switch result {
case .success(let location):
print(location.coordinate.latitude, location.coordinate.longitude)
case .failure(let error):
assertionFailure("Error getting the users location \(error)")
}
}
}
func getCurrentLocationCoordinates() {
locationService.newLocation = { result in
switch result {
case .success(let location):
print(location.coordinate.latitude, location.coordinate.longitude)
CLGeocoder().reverseGeocodeLocation(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 pmark = placemarks?[0]
self.displayLocationInfo(pmark)
} else {
print("Problem with the data received from geocoder")
}
})
case .failure(let error):
assertionFailure("Error getting the users location \(error)")
}
}
}
更新到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)
}
}
这里是结果屏幕
你应该做这些步骤:
add CoreLocation.framework to BuildPhases -> Link Binary With Libraries (no longer necessary as of XCode 7.2.1) import CoreLocation to your class - most likely ViewController.swift add CLLocationManagerDelegate to your class declaration add NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription to plist init location manager: locationManager = CLLocationManager() locationManager.delegate = self; locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestAlwaysAuthorization() locationManager.startUpdatingLocation() get User Location By: func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let locValue:CLLocationCoordinate2D = manager.location!.coordinate print("locations = \(locValue.latitude) \(locValue.longitude)") }
斯威夫特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.
最后但并非最不重要的,去你的信息。plist并启用“Privacy -Location when in Use Usage Description.”
当您使用模拟器测试时,它总是给您一个自定义位置,您在模拟器中配置->调试->位置。
首先在项目中添加两个框架
1:地
2:共重定位(从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