如何存储用户的当前位置,并在地图上显示该位置?

我可以在地图上显示预定义的坐标,只是不知道如何从设备接收信息。

我也知道我必须添加一些项目到Plist。我该怎么做呢?


当前回答

首先导入Corelocation和MapKit库:

import MapKit
import CoreLocation

从CLLocationManagerDelegate继承到我们的类

class ViewController: UIViewController, CLLocationManagerDelegate

创建一个locationManager变量,这将是你的位置数据

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()

从刚刚定义的userLocatin获取用户坐标:

let coordinations = CLLocationCoordinate2D(latitude: userLocation.coordinate.latitude,longitude: userLocation.coordinate.longitude)

定义你想要缩放的地图:

let span = MKCoordinateSpanMake(0.2,0.2) 将这两个组合起来得到region:

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)

关闭函数 }

从你的按钮或者其他你想要设置locationManagerDeleget为self的方式

现在允许显示位置

指定精度

locationManager.desiredAccuracy = kCLLocationAccuracyBest

授权:

 locationManager.requestWhenInUseAuthorization()

为了能够授权位置服务,您需要将这两行添加到您的plist

位置:

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)
        
    }
}

其他回答

首先在项目中添加两个框架

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
 override func viewDidLoad() {

    super.viewDidLoad()       
    locationManager.requestWhenInUseAuthorization();     
    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()
    }
    else{
        print("Location service disabled");
    }
  }

这是你的视图didload方法,在ViewController类中还包括mapStart更新方法,如下所示

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    var locValue : CLLocationCoordinate2D = manager.location.coordinate;
    let span2 = MKCoordinateSpanMake(1, 1)    
    let long = locValue.longitude;
    let lat = locValue.latitude;
    print(long);
    print(lat);        
    let loadlocation = CLLocationCoordinate2D(
                    latitude: lat, longitude: long            

   )     

    mapView.centerCoordinate = loadlocation;
    locationManager.stopUpdatingLocation();
}

另外,不要忘记添加CoreLocation。框架和MapKit。项目中的框架(从XCode 7.2.1开始不再需要)

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)")
        }
    }
}

斯威夫特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.”

当您使用模拟器测试时,它总是给您一个自定义位置,您在模拟器中配置->调试->位置。

下面是一个适用于我的复制粘贴示例。

http://swiftdeveloperblog.com/code-examples/determine-users-current-location-example-in-swift/

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    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.
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        determineMyCurrentLocation()
    }


    func determineMyCurrentLocation() {
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestAlwaysAuthorization()

        if CLLocationManager.locationServicesEnabled() {
            locationManager.startUpdatingLocation()
            //locationManager.startUpdatingHeading()
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let userLocation:CLLocation = locations[0] as CLLocation

        // Call stopUpdatingLocation() to stop listening for location updates,
        // other wise this function will be called every time when user location changes.

       // manager.stopUpdatingLocation()

        print("user latitude = \(userLocation.coordinate.latitude)")
        print("user longitude = \(userLocation.coordinate.longitude)")
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
    {
        print("Error \(error)")
    }
}