UILabel not updating with new value

I have a UILabel and its attirbutedText value is set to something like "8 km/h" and is changing succesfully to other similar values. Later I want to set the attributedText with value of "-". I am dispatching the update on the main queue. The code for the update is called but it never updates on the screen and the previous assigned value stays.


     controller.speedValueLabel.attributedText = NSAttributedString(string: "-")

One way to call this code is when tapping a button. When this happens the label updates with "-". Another way is in the block of a timer. The timer is started and stopped on the main thread. When it fires it does nothing and the UILabel is just not updated. I tried with similar timer (but another one) and it also updated succesfully. What can be wrong?

Accepted Reply

The issue is now fixed. It turned out that there was previous update on the same UILabel that was made on a background thread. It also did not update the label. Then even though the new update was done on the main thread it was not working. Maybe because the value was the same as the one that was set on a background thread.

Replies

Could you show more code, where we see all the parts that you describe ?

Hi, thanks for your reply. Here is some part of the code:


This is an event that is being fired at some point.


ConnectionManager.shared.onConnectionShouldStop = { [weak self] in
            
            LogManager.sharedInstance.writeDebugInfo(forString: "Connection should stop. 5 seconds no valid response")
            
            guard let self = self else {
                return
            }
            
            BLEDiscoveryManager.shared.disconnectPeripheral()
            self.disconnectApp(adapterStopped: false)
            DispatchQueue.main.async {
                self.showDevicesMenu()
            }
            
  }

The update to the UILabel is part of the disconnectApp method. Part of disconnect:


func disconnectApp(adapterStopped: Bool) {
        
  //some more code that has nothing to do with the label and works properly
  //…
       
        DispatchQueue.main.async {
            self.peripheralsTableView.reloadData()
            self.updateEverywhereForConnectionLost()
        }
        
 }


Then at some point in updateEverywhereForConnectionLost:


DispatchQueue.main.async {
  for child in self.children {
            if child is SpeedViewController {
                let controller = child as! SpeedViewController
                LogManager.sharedInstance.writeDebugInfo(forString: “Assigning value“)
                controller.speedValueLabel.attributedText = NSAttributedString(string: "-")
            }
        }
}


To test this I have to go to a testing setup, so the debugging is done by logging to a file. The messages logged by LogManager are visible in the log, so the calls are made. But the UILabel does not update. Once or twice I saw it update with some delay of around 5 seconds, but after that it stopped updating at all.

The issue is now fixed. It turned out that there was previous update on the same UILabel that was made on a background thread. It also did not update the label. Then even though the new update was done on the main thread it was not working. Maybe because the value was the same as the one that was set on a background thread.

You create a new instance of the controller, that may be the reason.


Seems also that the quotes in “Assigning value“ or NSAttributedString(string: "-")

are not the correct double quotes.


Try this

DispatchQueue.main.async {
    for child in self.children where child is SpeedViewController {
            LogManager.sharedInstance.writeDebugInfo(forString: "Assigning value")
            child.speedValueLabel.attributedText = NSAttributedString(string: "-")
    }
}

OK, in fact you did upfate the label, but that was superseded by another update.


Note also that those UI updates may be stored for later execution in the main thread, all at once.


Don't forget to mark the thread as closed.