Search code examples
swiftalamofirecllocation

CLLocation + Weather(Alamofire) issues


I am trying to use CLLocation to capture longitude and latitude and then use the longitude and latitude in Alamofire to get weather. Every time, the longitude and latitude won't stop updating and the weather data won't print(if you wanna check it out here's an example link of the data: http://forecast.weather.gov/MapClick.php?lat=37.33233141&lon=-122.0312186&FcstType=json)

class SampleViewController: UIViewController, CLLocationManagerDelegate {
var locationManager:CLLocationManager!
var startLocation: CLLocation!
var isFetchingWeather = false

override func viewDidLoad() {
    super.viewDidLoad()
    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestAlwaysAuthorization()
   }

     override func viewDidAppear(_ animated: Bool) {
            getCurrentLocation()
     }
   func getCurrentLocation(){
    if CLLocationManager.locationServicesEnabled(){
        locationManager.startUpdatingLocation()

    }
}

     func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        var userLocation:CLLocation = locations[0]
        if isFetchingWeather != false{
    print("user latitude = \(userLocation.coordinate.latitude)")
    print("user longitude = \(userLocation.coordinate.longitude)")
    let requestLink = "http://forecast.weather.gov/MapClick.php?lat=\(userLocation.coordinate.latitude)&lon=\(userLocation.coordinate.longitude)&FcstType=json"
    print(requestLink)
    Alamofire.request(requestLink).validate().responseJSON
        { response in
            switch response.result {
            case .success(let data):
                let json = JSON(data)
                self.weatherData = json["data"].arrayValue
                    for weather in self.weatherData{
                    let temp = weather["weather"].stringValue
                       self.weatherString.append(temp)
                }
                print (self.weatherString)
                if self.startLocation == nil {
                    self.startLocation = userLocation as! CLLocation
                    self.locationManager.stopUpdatingLocation()
                }


            case .failure(let error):
                print(error)
            }
    }
        }
        else{
            print("is fetching weather is false")
        }

}


func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
{
    print("Error \(error)")
}
}

Thanks.


Solution

  • You really shouldn't run your weather request inside your location delegate. Instead, get your location in the didUpdateLocations delegate and save it to a var. Next, call stopUpdatingLocation() then call a separate function to make your weather request. Something like this:

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    
        let newLocation = locations.last
    
    //check accuracy and timestamp of location to make sure its not a cached/old location (if you don't care about accuracy or time, you can remove this check)
        let timeDiff = newLocation?.timestamp.timeIntervalSinceNow
    
        if timeDiff < 5.0 && (newLocation?.horizontalAccuracy)!<=self.accuracyNeeded{
    
            //stop updating location
            self.locationManager.stopUpdatingLocation()
    
            //set currentUserLocation
            self.myLocation=newLocation?.coordinate
    
    
            //call function to get weather
    
            //remove delegate
            self.locationManager.delegate = nil
    
        }
    
    }