Swift 3 - 存储用户位置并从不同的视图控制器调用它

Swift 3 - store the User Location and call it from different View Controllers

我是编程方面的新手,这是我的第一个应用程序,如果方法很糟糕,我们深表歉意。

我创建了一个辅助方法来获取用户位置,因为我需要从不同的视图控制器调用它,所以我认为这是一种更简洁的方法。但我不知道为什么现在不起作用(没有错误,它只是展示了欧洲的普遍看法)。但是当它在视图控制器中时,它工作得很好。

我从我正在学习的课程中获得了这种新方法,并且我一直在研究许多来源。我也检查了 但我还没有找到任何解决方案。

这是我在 GMSClient 文件中创建的方法。它将获取用户位置,但如果用户禁用此选项,它将显示默认位置(以柏林为中心):

    extension GMSClient: CLLocationManagerDelegate {

    //MARK: Initial Location: Berlin

    func setDefaultInitialLocation(_ map: GMSMapView) {
        let camera = GMSCameraPosition.camera(withLatitude: 52.520736, longitude: 13.409423, zoom: 8)
        map.camera = camera

        let initialLocation = CLLocationCoordinate2DMake(52.520736, 13.409423)
        let marker = GMSMarker(position: initialLocation)
        marker.title = "Berlin"
        marker.map = map

    }

    //MARK: Get user location

    func getUserLocation(_ map: GMSMapView,_ locationManager: CLLocationManager) {

        var userLocation: String?

        locationManager.requestWhenInUseAuthorization()

        func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

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

                map.isMyLocationEnabled = true
                map.settings.myLocationButton = true

            } else {
                setDefaultInitialLocation(map)
            }
        }

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

            if let location = locations.first {

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

                locationManager.stopUpdatingLocation()

                //Store User Location
                userLocation = "\(location.coordinate.latitude), \(location.coordinate.longitude)"
                print("userLocation is: \((userLocation) ?? "No user Location")")

            }
        }
    }
}

这个文件也有这个单例:

// MARK: Shared Instance

    class func sharedInstance() -> GMSClient {
        struct Singleton {
            static var sharedInstance = GMSClient()
        }
        return Singleton.sharedInstance
    }

然后我在我的视图控制器中这样调用它:

class MapViewController: UIViewController, CLLocationManagerDelegate {

    // MARK: Outlets

    @IBOutlet weak var mapView: GMSMapView!


    // MARK: Properties

    let locationManager = CLLocationManager()
    var userLocation: String?
    let locationManagerDelegate = GMSClient()


    // MARK: Life Cycle

    override func viewDidLoad() {

        super.viewDidLoad()

        self.locationManager.delegate = locationManagerDelegate

        GMSClient.sharedInstance().getUserLocation(mapView, locationManager)

    }

有人知道什么地方可能出错吗?

谢谢!

我猜问题出在这里,

self.locationManager.delegate = locationManagerDelegate

您创建了 GMSClient 的新实例,并将其保存在存储的 属性 中,并且该实例被设置为 CLLocationManager 的委托 属性。

你需要这样做,

self.locationManager.delegate = GMSClient.sharedInstance()

您需要这样做,因为您希望 GMSClient 的单例实例成为 CLLocationManager 的委托而不是新实例。这样你的单身人士 class 就会收到来自 CLLocationManager class.

要详细了解您的代码为何不起作用,我建议您阅读更多有关对象、实例、实例变量、单例、委托设计模式的内容。

按照 Paulw11 所说的,我找到了使用通知的更快解决方案。

  1. 从第一个视图控制器中的 LocationManager 委托方法发送通知:

    class MapViewController: CLLocationManagerDelegate {
    
        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]
    
                        NotificationCenter.default.post(name: NSNotification.Name("UserLocationNotification"), object: self, userInfo: userInfo as [NSObject : AnyObject])
    
                    }
                }
         }
    
  2. 将第二个视图控制器设置为观察者。这样我就可以存储 userLocation 并在以后将其用于搜索请求:

    class NeighbourhoodPickerViewController: UIViewController, UITextFieldDelegate {
    
    var userLocation: String?
    var currentLocation: CLLocation!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        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 {
            self.currentLocation = userInfo
            self.userLocation = "\(userInfo.coordinate.latitude), \(userInfo.coordinate.longitude)"
        }
    }