ios location city

There’ve been four articles in this series on building a simple weather iOS weather app with Swift: In this article, we’re going to take what we’ve learned from our little geolocation app and make some changes to our weather app so that: To get the weather for a given city using OpenWeatherMap’s “current weather” API, we’ve been using this call: There’s also a way to get the weather for a given latitude and longitude.It’s done by making this call: I’m based in Tampa, whose coordinates are 27.9506° N, 82.4572° W. That translates into: Another way of getting the current weather for Tampa from OpenWeatherMap is to make the call below.. Try pasting the URL into your browser’s address bar (using your own API key, of course): We’re going to make some additional to our weather app so that it can do this programatically.Here’s an updated version of the WeatherGetter class, which we use to connect to OpenWeatherMap and get weather data: import Foundation // MARK: WeatherGetterDelegate // =========================== // WeatherGetter should be used by a class or struct, and that class or struct // should adopt this protocol and register itself as the delegate.

// The delegate's didGetWeather method is called if the weather data was // and successfully converted from JSON into // a Swift dictionary.
iqos price amazon// The delegate's didNotGetWeather method is called if either: // - , or // - The received weather data could not be converted from JSON into a dictionary.
salesforce iosprotocol WeatherGetterDelegate { func didGetWeather(weather: Weather) func didNotGetWeather(error: NSError) } // MARK: WeatherGetter // =================== class WeatherGetter { /data/2.5/weather" private let openWeatherMapAPIKey = "06db44f389d2172e9b1096cdce7b051c" private var delegate: WeatherGetterDelegate // MARK: - init(delegate: WeatherGetterDelegate) { self.delegate = delegate } func getWeatherByCity(city: String) { let weatherRequestURL = NSURL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
iqos inmedio

getWeather(weatherRequestURL) } func getWeatherByCoordinates(latitude latitude: Double, longitude: Double) { let weatherRequestURL = NSURL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&lat=\(latitude)&lon=\(longitude)")!
iqos whitegetWeather(weatherRequestURL) } private func getWeather(weatherRequestURL: NSURL) { // This is a pretty simple networking task, so the shared session will do.
best stationary vaporizer 2015let session = NSURLSession.sharedSession() session.configuration.timeoutIntervalForRequest = 3 // The data task retrieves the data.
wings vaporizerlet dataTask = session.dataTaskWithURL(weatherRequestURL) { (data: NSData?, response: NSURLResponse?, error: NSError?)
ios warhammer review

in if let networkError = error { // Case 1: Error // An error occurred while trying to get data from the server.
ios location background modeself.delegate.didNotGetWeather(networkError) } else { // Case 2: Success // We got data from the server!
ios online djdo { // Try to convert that data into a Swift dictionary let weatherData = try NSJSONSerialization.JSONObjectWithData( data!, options: .MutableContainers) as![String: AnyObject] // If we made it to this point, we've successfully converted the // JSON-formatted weather data into a Swift dictionary.// Let's now used that dictionary to initialize a Weather struct.let weather = Weather(weatherData: weatherData) // Now that we have the Weather struct, let's notify the view controller, // which will use it to display the weather to the user.

self.delegate.didGetWeather(weather) } catch let jsonError as NSError { // An error occurred while trying to convert the data into a Swift dictionary.self.delegate.didNotGetWeather(jsonError) } } } // The data task is set up...launch it!dataTask.resume() } } 123456789 { (: ) (: )} { = = : (: ) {.= } (: ) { = (: "\()\()\()")!()}(: , : ) { = (: "\()\()\()\()")!()}(: ) { = .()..= 3 = .(){(: ?, : ?, : ?){ { = .(!,:[: ] = (: )..()}We’ve made a couple of changes: We’ve added one button with the title Get weather for your current location and put it between the weather data labels and the controls for entering a city’s name.It’s assigned the following: We’ve also updated the view controller code: import UIKit import CoreLocation class ViewController: UIViewController, WeatherGetterDelegate, CLLocationManagerDelegate, UITextFieldDelegate { @IBOutlet weak var cityLabel: UILabel!@IBOutlet weak var weatherLabel: UILabel!

@IBOutlet weak var temperatureLabel: UILabel!@IBOutlet weak var cloudCoverLabel: UILabel!@IBOutlet weak var windLabel: UILabel!@IBOutlet weak var rainLabel: UILabel!@IBOutlet weak var humidityLabel: UILabel!@IBOutlet weak var getLocationWeatherButton: UIButton!@IBOutlet weak var cityTextField: UITextField!@IBOutlet weak var getCityWeatherButton: UIButton!let locationManager = CLLocationManager() var weather: WeatherGetter!// MARK: - override func viewDidLoad() { super.viewDidLoad() weather = WeatherGetter(delegate: self) // Initialize UI // ------------- cityLabel.text = "simple weather" weatherLabel.text = "" temperatureLabel.text = "" cloudCoverLabel.text = "" windLabel.text = "" rainLabel.text = "" humidityLabel.text = "" cityTextField.text = "" cityTextField.placeholder = "Enter city name" cityTextField.delegate = self cityTextField.enablesReturnKeyAutomatically = true getCityWeatherButton.enabled = false getLocation() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // MARK: - Button events and states // -------------------------------- @IBAction func getWeatherForLocationButtonTapped(sender: UIButton) { setWeatherButtonStates(false) getLocation() } @IBAction func getWeatherForCityButtonTapped(sender: UIButton) { guard let text = cityTextField.text where !text.trimmed.isEmpty else { return } setWeatherButtonStates(false) weather.getWeatherByCity(cityTextField.text!.urlEncoded) } func setWeatherButtonStates(state: Bool) { getLocationWeatherButton.enabled = state getCityWeatherButton.enabled = state } // MARK: - WeatherGetterDelegate methods // ----------------------------------- func didGetWeather(weather: Weather) { // This method is called asynchronously, which means it won't execute in the main queue.

// All UI code needs to execute in the main queue, which is why we're wrapping the code // that updates all the labels in a dispatch_async() call.dispatch_async(dispatch_get_main_queue()) { self.cityLabel.text = weather.city self.weatherLabel.text = weather.weatherDescription self.temperatureLabel.text = "\(Int(round(weather.tempCelsius)))°" self.cloudCoverLabel.text = "\(weather.cloudCover)%" self.windLabel.text = "\(weather.windSpeed) m/s" if let rain = weather.rainfallInLast3Hours { self.rainLabel.text = "\(rain) mm" } else { self.rainLabel.text = "None" } self.humidityLabel.text = "\(weather.humidity)%" self.getLocationWeatherButton.enabled = true self.getCityWeatherButton.enabled = self.cityTextField.text?.characters.count > 0 } } func didNotGetWeather(error: NSError) { // This method is called asynchronously, which means it won't execute in the main queue.// All UI code needs to execute in the main queue, which is why we're wrapping the call // to showSimpleAlert(title:message:) in a dispatch_async() call.

dispatch_async(dispatch_get_main_queue()) { self.showSimpleAlert(title: "Can't get the weather", message: "The weather service isn't responding.")self.getLocationWeatherButton.enabled = true self.getCityWeatherButton.enabled = self.cityTextField.text?.characters.count > 0 } print("didNotGetWeather error: \(error)") } // MARK: - CLLocationManagerDelegate and related methods func getLocation() { guard CLLocationManager.locationServicesEnabled() else { showSimpleAlert( title: "Please turn on location services", message: "This app needs location services in order to report the weather " + "for your current location.
" + "Go to Settings → Privacy → Location Services and turn location services on.") getLocationWeatherButton.enabled = true return } let authStatus = CLLocationManager.authorizationStatus() guard authStatus == .AuthorizedWhenInUse else { switch authStatus { case .Denied, .Restricted: let alert = UIAlertController( title: "Location services for this app are disabled", message: "In order to get your current location, please open Settings for this app, choose \"Location\" and set \"Allow location access\" to \"While Using the App\".",

preferredStyle: .Alert ) let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil) let openSettingsAction = UIAlertAction(title: "Open Settings", style: .Default) { action in if let url = NSURL(string: UIApplicationOpenSettingsURLString) { UIApplication.sharedApplication().openURL(url) } } alert.addAction(cancelAction) alert.addAction(openSettingsAction) presentViewController(alert, animated: true, completion: nil) getLocationWeatherButton.enabled = true return case .NotDetermined: locationManager.requestWhenInUseAuthorization() default: print("Oops!Shouldn't have come this far.")} return } locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers locationManager.requestLocation() } func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let newLocation = locations.last!

weather.getWeatherByCoordinates(latitude: newLocation.coordinate.latitude, longitude: newLocation.coordinate.longitude) } func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { // This method is called asynchronously, which means it won't execute in the main queue.dispatch_async(dispatch_get_main_queue()) { self.showSimpleAlert(title: "Can't determine your location", message: "The GPS and other location services aren't responding.")} print("locationManager didFailWithError: \(error)") } // MARK: - UITextFieldDelegate and related methods // ----------------------------------------------- // Enable the "Get weather for the city above" button // if the city text field contains any text, // disable it otherwise.func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let currentText = textField.text ??"" let prospectiveText = (currentText as NSString).stringByReplacingCharactersInRange( range, withString: string).trimmed getCityWeatherButton.enabled = prospectiveText.characters.count > 0 return true } // Pressing the clear button on the text field (the x-in-a-circle button // on the right side of the field) func textFieldShouldClear(textField: UITextField) -> Bool { // Even though pressing the clear button clears the text field, // this line is necessary.

I'll explain in a later blog post.textField.text = "" getCityWeatherButton.enabled = false return true } // Pressing the return button on the keyboard should be like // pressing the "Get weather for the city above" button.func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() getWeatherForCityButtonTapped(getCityWeatherButton) return true } // Tapping on the view should dismiss the keyboard.override func touchesBegan(touches: Set
, withEvent event: UIEvent?){ view.endEditing(true) } // MARK: - Utility methods // ----------------------- func showSimpleAlert(title title: String, message: String) { let alert = UIAlertController( title: title, message: message, preferredStyle: .Alert ) let okAction = UIAlertAction( title: "OK", style: .Default, handler: nil ) alert.addAction(okAction) presentViewController( alert, animated: true, completion: nil ) } } extension String { // A handy method for %-encoding strings containing spaces and other // characters that need to be converted for use in URLs.

var urlEncoded: String { return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet())!} var trimmed: String { return self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) } } 123456789 : ,,,{@ : !@ : !@ : !@ : !@ : !@ : !@ : !@ : !@ : !@ : != () : != ()} () {.()}@(: ) {()()}@ (: ) { = .= } (: ) {(()) {.. = ... = ... = "\(((.).. = "\(.).. = "\(.){.. = "\()} {.. = }.. = "\(.).. = .. = ..?.. > 0}} (: ) {(()) {.(:,: ).. = .. = ..?.. > 0}(\()")} () {.(){(: ,: + +).= } = .(){ { ., .: = (: ,: ,: .)= (: , : ., : ) = (: , : .){ = (: ) {.().()}}.().()(,: , : ).(: , : []) { = .!.(:..,: ..)} (: , : ) {(()) {.(:,: )}(\()")} (: ,: ,: ) { = .).. = .. > 0 } (: ) {.= } (: ) {.()()} (: <>, : ?)(: , : ) { = (: ,: ,: .)= (: ,:.,: ).()(,:,: )}} { : { .(.())!}Let’s take a closer look at the view controller code… Here’s the section of the code for the buttons: // MARK: - Button events and states // -------------------------------- @IBAction func getWeatherForLocationButtonTapped(sender: UIButton) { setWeatherButtonStates(false) getLocation() } @IBAction func getWeatherForCityButtonTapped(sender: UIButton) { guard let text = cityTextField.text where !text.trimmed.isEmpty else { return } setWeatherButtonStates(false) weather.getWeatherByCity(cityTextField.text!.urlEncoded) } func setWeatherButtonStates(state: Bool) { getLocationWeatherButton.enabled = state getCityWeatherButton.enabled = state } 123456789 @ (: ) {()()}@ (: ) { = .

= } The getWeatherForLocationButtonTapped method handles the case when the user presses the Get weather for your current location button, while the getWeatherForCityButtonTapped method handles the case when the user presses the Get weather for the city above button.Both methods disable both buttons when pressed by calling the setWeatherButtonStates method, and the buttons are re-enabled once either a weather report or error message has been obtained.Here’s the section for the WeatherGetterDelegate methods: // MARK: - WeatherGetterDelegate methods // ----------------------------------- func didGetWeather(weather: Weather) { // This method is called asynchronously, which means it won't execute in the main queue.self.getLocationWeatherButton.enabled = true self.getCityWeatherButton.enabled = self.cityTextField.text?.characters.count > 0 } print("didNotGetWeather error: \(error)") } 123456789 (: ) {(()) {.. = ... = ... = "\(((.).. = "\(.).. = "\(.)

,: ).. = .. = ..?.. > 0}(\()")} The view controller adopts the WeatherGetterDelegate protocol, which has two required methods: Both methods are called from the closure provided to the data task defined in WeatherGetter‘s getWeather method.This means that they’re not being executed in the main queue.Both methods’ primary function is to make changes to the UI, which must be done in the main queue.That’s why I put the UI code in these methods into a dispatch_async block specifying that the block must be executed in the main queue.Here’s the code for the CLLocationManagerDelegate and related methods: // MARK: - CLLocationManagerDelegate and related methods func getLocation() { guard CLLocationManager.locationServicesEnabled() else { showSimpleAlert( title: "Please turn on location services", message: "This app needs location services in order to report the weather " + "for your current location.
" + "Go to Settings → Privacy → Location Services and turn location services on."

} print("locationManager didFailWithError: \(error)") } 123456789 () {.(),: )}(\()")} Most of getLocation() is concerned with ruling out cases where we can’t get the user’s location.Only the last three lines of the method deal with getting location updates from locationManager.If control made it past the first two guard statements, it means that location services has been activated for the device and the user has given our app permission to use location services while the app is active.The following happens: Once requestLocation is called, one of two methods will be called as a result: // MARK: - UITextFieldDelegate and related methods // ----------------------------------------------- // Enable the "Get weather for the city above" button // if the city text field contains any text, // disable it otherwise.{ view.endEditing(true) } 123456789 (: ,: ,: ) { = .A quick explanation of each of these methods: // MARK: - Utility methods // ----------------------- func showSimpleAlert(title title: String, message: String) { let alert = UIAlertController( title: title, message: message, preferredStyle: .Alert ) let okAction = UIAlertAction( title: "OK", style: .Default, handler: nil ) alert.addAction(okAction) presentViewController( alert, animated: true, completion: nil ) } extension String { // A handy method for %-encoding strings containing spaces and other // characters that need to be converted for use in URLs.