Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UILabel text updated inside a Swift closure refuses to show

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()

}
like image 360
bombaypundit Avatar asked Dec 05 '25 13:12

bombaypundit


1 Answers

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.

like image 181
Daniel Galasko Avatar answered Dec 07 '25 14:12

Daniel Galasko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!