While learning Swift, I am coding a simple practice iOS app to scrape weather info for a given city from a site and show it in a UILabel.
The code uses a "NSURLSession.sharedSession().dataTaskWithURL" closure. Although I'm able to fetch the data correctly and capture the relevant text in the "UILabel.text", I can't get the actual app to show the updated UILabel.
What am I doing wrong? Here is the relevant code:
@IBAction func buttonPressed(sender: AnyObject) {
var urlString = "http://www.weather-forecast.com/locations/" + cityName.text.stringByReplacingOccurrencesOfString(" ", withString: "") + "/forecasts/latest"
var url = NSURL(string: urlString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as String
var contentArray = urlContent.componentsSeparatedByString("<span class=\"phrase\">")
var weatherInfo = contentArray[1].componentsSeparatedByString("</span>")
self.resultShow.text = weatherInfo[0] // Text does not show in the app
println(weatherInfo[0]) // This works correctly
println(self.resultShow.text) // This works correctly
}
task.resume()
}
You need to perform your UI updates on the main thread
NSURLSession completion handlers will always be called on the background thread. To update your UI a simple dispatch_async to the main thread should suffice:)
@IBAction func buttonPressed(sender: AnyObject) {
var urlString = "http://www.weather-forecast.com/locations/" + cityName.text.stringByReplacingOccurrencesOfString(" ", withString: "") + "/forecasts/latest"
var url = NSURL(string: urlString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as String
var contentArray = urlContent.componentsSeparatedByString("<span class=\"phrase\">")
var weatherInfo = contentArray[1].componentsSeparatedByString("</span>")
dispatch_async(dispatch_get_main_queue(), {
//perform all UI stuff here
self.resultShow.text = weatherInfo[0]
})
}
task.resume()
}
EDIT
Whilst not important here since the closure is not retained, in some instances it's important to explicitly declare capture lists to avoid retain cycles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With