斯威夫特3 - 存储用户的位置,并从不同的视图控制器

问题描述:

称它为我在编程很新,这是我的第一个应用程序,很抱歉,如果该方法是非常寒酸。斯威夫特3 - 存储用户的位置,并从不同的视图控制器

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

我从我在做的过程中这种新的方法,我已经在许多来源一直在研究。我也检查了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) 

    } 

任何人有什么想法可能是错的?

谢谢!

+1

你嵌套你'getUserLocation'函数内部的委托功能。这不起作用。将它们移出。 – Paulw11

+0

我之前曾尝试过并且确实奏效,但我想稍后创建一个完成处理程序,以获取Google地图Web搜索请求的用户位置。就像...'func getUserLocation(_ map:GMSMapView,_ locationManager:CLLocationManager,completionHandlerForUserLocation:@escaping(_ userLocation:String ?, _error:NSError?) - > Void)){'所以我不知道如何使用委托方法... – celiux

+1

说实话,完成处理程序可能不是这里正确的模式。你可以使用NSNotification,或者你可以设置一个委托或者在一个属性中存储一个闭包。我可能会使用NSNotification,因为它允许您轻松通知多个观察者 – Paulw11

我想这个问题就在这里,

self.locationManager.delegate = locationManagerDelegate 

您已经创建的GMSClient一个新实例,并在存储的属性保存它和实例设置为CLLocationManager委托财产。

你需要这样做,而不是,

self.locationManager.delegate = GMSClient.sharedInstance() 

你需要这样做,因为你想的GMSClient单一实例成为CLLocationManager委托,而不是一个新的实例。这样,您的单身人士课程将接收来自 CLLocationManager类的回调。

要了解更多关于为什么你的代码是不工作,我建议你阅读更多关于对象,实例,实例变量,单身,委托设计模式。

+0

感谢您的回复。你的意思是更好地做到这一点? locationManager.delegate = self。但它也不起作用。我也尝试删除它,仍然是相同的... – celiux

+0

设置单身实例作为委托,正如我在答案中提到的。 –

+1

我做了你所说的但仍然一样。也许不是代表团的问题?是的,我知道......我花了几个小时阅读有关该节目的基础知识,但仍然很难理解,我想一旦我开始做真正的东西,它会随着时间而来。但我今天将更详细地研究那个singelton /共享实例和代表。 – celiux

继Paulw11说什么,我发现用通知的更快的解决方案。从第一视图控制器内的的LocationManager委托方法

  1. 发送通知:

    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. 设置第二视图控制器作为观察者。这样我可以存储用户位置并在以后使用它的搜索请求:

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