Swift 3.0 从不同的视图控制器获取用户位置坐标

Swift 3.0 Get User Location Coordinates from Different View Controller

我有两个视图控制器 - 一个带有能够通过 locationManager 获取用户位置坐标的 mapView,第二个 VC 我希望能够提取这些用户坐标。

第一个VC:MapView

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    var coordinatesOfUser = locations.last?.coordinate
    print("The value of usercoordinates are \(coordinatesOfUser)")

    // here I want to be able to pull this variable, coordinatesOfUser


    if let location = locations.last {
        let span = MKCoordinateSpanMake(0.00775, 0.00775)
        let myLocation = CLLocationCoordinate2DMake(location.coordinate.latitude,location.coordinate.longitude)
        let region = MKCoordinateRegionMake(myLocation, span)
        map.setRegion(region, animated: true)
    }
    self.map.showsUserLocation = true
    locationManager.stopUpdatingLocation()


}

第二个VC:

我正在考虑在此 VC 中调用 locationManager 函数。这是将坐标拉到这个 VC 的最有效方法吗?如果是这样,我该怎么做?

这里有几个选项可以解决这个问题:

Delegation:您的第二个 VC 可以有一个委托,允许第一个视图控制器从中获取坐标。这样做的好处是您可以在进来时收到更新。

protocol MyLocationDelegate: class {
    func newLocationArrived(location: CLLocation)
}

class FirstVC: UIViewController, MyLocationDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func newLocationArrived(location: CLLocation) {
        print(location)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let dest = segue.destination as? SecondVC {
            dest.delegate = self
        }
    }
}

class SecondVC: UIViewController, CLLocationManagerDelegate {

    /// ... ...

    weak var delegate: MyLocationDelegate?

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        /// do something with the location

        /// provide the data via delegation
        delegate?.newLocationArrived(location: CLLocation())
    }
}

Notifications: Post 通过 NSNotificationCenter 的通知。也能够在进来时接收更新,只需通过通知中心而不是通过委托发送。

postNotificationName:object:userInfo:

子视图控制器:根据第二个视图控制器及其视图是否是第一个视图控制器的子视图,这可能允许直接访问。并不总是一个选择。

Singleton (CLLocationManager):如果您打算在整个应用程序的其他地方使用位置服务,您可以将 CLLocationManager 移动到它自己的 class 中,并使用 Singleton .其他视图控制器可以参考 class 以满足他们的特定需求。这在使用背景或重大更改位置时也很有用,因为他们可能需要使用 LaunchOptions 密钥来重新启动位置管理器。

class MyLocationManager: CLLocationManager, CLLocationManagerDelegate {

    static let shared = MyLocationManager()

    var locations = [CLLocation]()

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        for location in locations {
            self.locations.append(location)
        }
    }
}

我遇到了同样的问题,最后我用通知修复了它,正如 kuhncj 所说。

代码最后是这样的:

    //Get user location
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

            if status == .authorizedWhenInUse {
                locationManager.startUpdatingLocation()

                mapView.isMyLocationEnabled = true
                mapView.settings.myLocationButton = true
            } else {
                initialLocation()
            }
        }

        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

            if let location = locations.first {

                mapView.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)

                locationManager.stopUpdatingLocation()

                let userInfo: NSDictionary = ["location": location]

                //Post notification
                NotificationCenter.default.post(name: NSNotification.Name("UserLocationNotification"), object: self, userInfo: userInfo as [NSObject : AnyObject])

            }
        }

然后在另一个视图控制器中:

    var userLocation: String?

    override func viewDidLoad() {
            super.viewDidLoad()

            //Observer that receives the notification
            NotificationCenter.default.addObserver(self, selector: #selector(locationUpdateNotification), name: Notification.Name("UserLocationNotification"), object: nil)

        }

        func locationUpdateNotification(notification: NSNotification) {
            if let userInfo = notification.userInfo?["location"] as? CLLocation {
                //Store user location
                self.userLocation = "\(userInfo.coordinate.latitude), \(userInfo.coordinate.longitude)"
            }
        }

然后我可以将存储的 userLocation 用于其他方法。