【问题标题】:Swift 3 - store the User Location and call it from different View ControllersSwift 3 - 存储用户位置并从不同的视图控制器调用它
【发布时间】:2017-07-08 09:33:10
【问题描述】:

我是编程新手,这是我的第一个应用程序,如果方法非常简陋,请见谅。

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

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

这是我在 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")")

            }
        }
    }
}

这个文件也有这个singelton:

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

    }

任何人都知道可能出了什么问题?

谢谢!

【问题讨论】:

  • 您已将委托函数嵌套在 getUserLocation 函数中。这行不通。把它们移走。
  • 我之前尝试过并且确实有效,问题是我想稍后创建一个完成处理程序,以便获取谷歌地图网络搜索请求的用户位置。类似于...func getUserLocation(_ map: GMSMapView,_ locationManager: CLLocationManager, completionHandlerForUserLocation: @escaping (_ userLocation: String?, _ error: NSError?) -> Void)) { 所以我不知道如何使用委托方法...
  • 老实说,完成处理程序在这里可能不是正确的模式。你可以使用 NSNotification 或者你可以设置一个委托或者在一个属性中存储一个闭包。我可能会使用 NSNotification,因为它可以让您轻松通知多个观察者
  • 哦,我明白了,我从未使用过 NSNotifications。我会查的!感谢您的回答,我找到了这个thread,它已经很老了,但我认为它可以解决我的问题。稍后我会提供更新!

标签: ios swift mapkit google-maps-sdk-ios


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我猜问题出在这里,

    self.locationManager.delegate = locationManagerDelegate
    

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

    你需要这样做,

    self.locationManager.delegate = GMSClient.sharedInstance()
    

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

    要了解更多关于您的代码为何无法运行的信息,我建议您阅读有关对象、实例、实例变量、单例、委托设计模式的更多信息。

    【讨论】:

    • 感谢您的回复。你的意思是更好地做到这一点? locationManager.delegate = 自我。但它也不起作用。我也试过删除它,但还是一样...
    • 将单例实例设置为我在答案中提到的委托。
    • 我按照你说的做了,但还是一样。也许不是代表团的问题?是的,我知道...我花了几个小时阅读有关编程基础的知识,但仍然很难理解,我想一旦我开始做真正的事情就会随着时间的推移而出现。但我今天将更专门地研究单格顿/共享实例和委托。
    猜你喜欢
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-02
    相关资源
    最近更新 更多