LinShiwei LinShiwei - 1 month ago 13
Swift Question

UILabel doesn't update after setting attributedText

I use MapKit to record running distance. I have the following code:

var runningDistance : Double = 0{
didSet{
guard let text = runningDistanceLabel.attributedText as? NSMutableAttributedString else{return}
let range = NSMakeRange(0, 4)
let attributeString = NSAttributedString(string: String(format:"%.2f",runningDistance/1000.0), attributes: [
"NSFontAttributeName":UIFont(name: "DINCondensed-Bold", size: 17)
])
text.replaceCharacters(in: range, with: attributeString)
runningDistanceLabel.attributedText = text

print(runningDistanceLabel.text)
print(runningDistanceLabel.attributedText)
}
}


When
userLocation
update, I calculate the distance and set
runningDistance
.

In console:

Optional("0.04公里")
Optional(0.04{
NSFontAttributeName = "Optional(<UICTFont: 0x7ff79b7b7250> font-family: \"DIN Condensed\"; font-weight: bold; font-style: normal; font-size: 17.00pt)";
}公里{
NSFont = "<UICTFont: 0x7ff79d800110> font-family: \".PingFangSC-Regular\"; font-weight: normal; font-style: normal; font-size: 14.00pt";
NSParagraphStyle = "Alignment 2, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 4, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0";
})


That shows the
runningDistanceLabel
's
text
and
attributedText
has been set and changed. But in simulator, the label's text remains unchanged.

And if I replace:

runningDistanceLabel.attributedText = text


with:

runningDistanceLabel.text = "\(runningDistance)"


Then in simulator, the label's text can be changed normally.

What's wrong with my code about setting attributedText? How to set
attributedText
and update correctly in simulator?

Thank you very much!

Edit:

I am sure the
guard
has been passed because it has printed label's text and attributedText in console and I have added a breakpoint to test it.

I also try:

DispatchQueue.main.async {[unowned self] in
self.runningDistanceLabel.attributedText = text
}


But I still cannot update the label's text.

Soluion

And with Rroobb's help, I add a line of code to set label's text before setting its attributedText:

runningDistanceLabel.text = String(format:"%.2f",runningDistance/1000.0) + "公里"
runningDistanceLabel.attributedText = text


And in simulator, the label's text can be updated now. Amazing!

In iOS document about
UILabel
's
attributedText
:


Assigning a new value to this property also replaces the value of the text property with the same string data, albeit without any formatting information.


It seems that setting
attributedText
can automatically change the
text
property.

But here I don't know why I should set
text
before setting
attributedText
in order to update the label's text.

Answer

This works, I added two line of code :

 var runningDistance : Double = 0.0 {
    didSet{
        guard let text = runningDistanceLabel.attributedText as? NSMutableAttributedString else{

            return

        }

        let range = NSMakeRange(0, 4)
        runningDistanceLabel.text = String(format:"%.2f",runningDistance/1000.0) //here
        runningDistanceLabel.font = UIFont(name: "DINCondensed-Bold", size: 17) // here
        let attributeString = NSAttributedString(string: String(format:"%.2f",runningDistance/1000.0), attributes: [
            "NSFontAttributeName":UIFont(name: "DINCondensed-Bold", size: 17)!
            ])

        text.replaceCharacters(in: range, with: attributeString)
        runningDistanceLabel.attributedText = text


        print(runningDistanceLabel.text!)
        print(runningDistanceLabel.attributedText!)
    }
}