2017-07-08 9 views
1

稱它爲我在編程很新,這是我的第一個應用程序,很抱歉,如果該方法是非常寒酸。斯威夫特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

回答

1

我想這個問題就在這裏,

self.locationManager.delegate = locationManagerDelegate 

您已經創建的GMSClient一個新實例,並在存儲的屬性保存它和實例設置爲CLLocationManager委託財產。

你需要這樣做,而不是,

self.locationManager.delegate = GMSClient.sharedInstance() 

你需要這樣做,因爲你想的GMSClient單一實例成爲CLLocationManager委託,而不是一個新的實例。這樣,您的單身人士課程將接收來自 CLLocationManager類的回調。

要了解更多關於爲什麼你的代碼是不工作,我建議你閱讀更多關於對象,實例,實例變量,單身,委託設計模式。

+0

感謝您的回覆。你的意思是更好地做到這一點? locationManager.delegate = self。但它也不起作用。我也嘗試刪除它,仍然是相同的... – celiux

+0

設置單身實例作爲委託,正如我在答案中提到的。 –

+1

我做了你所說的但仍然一樣。也許不是代表團的問題?是的,我知道......我花了幾個小時閱讀有關該節目的基礎知識,但仍然很難理解,我想一旦我開始做真正的東西,它會隨着時間而來。但我今天將更詳細地研究那個singelton /共享實例和代表。 – celiux

1

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