1

I have a convenience extension like this:

extension NSMutableAttributedString {

    func append(string: String, attributes: [String: Any]) {
        let attributed = NSMutableAttributedString(string: string)
        let range = NSRange(location: 0, length: string.utf16.count)
        for (attribute, value) in attributes {
            attributed.addAttribute(attribute, value: value, range: range)
        }
        append(attributed)
    }
}

I'm styling text in my UILabel thusly:

let normalAttributes = [NSForegroundColorAttributeName: darkGray]
let lightAttributes = [NSForegroundColorAttributeName: lightGray]
let text = NSMutableAttributableString()
text.append("Part 1", attributes: normalAttributes)
text.append("Part 2", attributes: lightAttributes)

All of this within a custom UITableViewCell class. What's happening is that the text is rendering with the base color in the NIB file, rather than the custom foreground color as per my attributed string - until I do something (like scroll around) that causes cell reuse, after which suddenly the colors render correctly.

I can't seem to find anything wrong with the lifecycle of the object, and there's no other place that's messing with this label. The label, fwiw, is an IBOutlet, so I'm not creating a new one each time or anything strange.

  • "I'm styling text in my UILabel thusly" But _wherely_ are you running that codely? Context (and timing) is everything. – matt Sep 25 '17 at 21:07
  • 1
    Your convenience extension is doing a lot of unnecessary work. It can be replaced with `append(NSAttributedString(string: string, attributes: attributes))`. – Lily Ballard Sep 25 '17 at 21:13
  • Are you modifying the label from the main thread or from a background thread? Having UI updates not actually show up until you force a re-rendering is a hallmark of touching the UI from a background thread. – Lily Ballard Sep 25 '17 at 21:15
  • @matt this is all happening in cellForRowAtIndexPath on main thread – Kiril Savino Sep 26 '17 at 15:14
  • @KevinBallard should be on main thread - and thanks for that simplification, trying to remember why I'm doing it the way I am... probably left over from something. :) – Kiril Savino Sep 26 '17 at 15:15
  • 1
    @KirilSavino But you're still just _talking_ about your code. Please show your _actual code_. Show enough of it that I would be able to reproduce the entire phenomenon in question. The fact that you don't see anything until you scroll is very suggesting that something is wrong at the call site. Show `cellForRow` itself. – matt Sep 26 '17 at 15:25

2 Answers2

5

Turns out it's the same problem as:

Attributed string in tableviewcell not showing bold text until the cell is dequeued and reloaded

So it's solved by setting the font & color to nil on the label before setting the attributeText. Annoying, but easy enough to do that work-around.

0

As @Kiril Savino suggested. Setting up Font & Color of UILabel to nil is do easy work-around to get it done.

But one more thing I noticed today is Default Font used from Storyboard or XIB.

It should be System Font from Storyboard or XIB to make this work. If you have used other Custom Font, then it won't work.

So, make sure Default Font of UILabel should System Font.

Thank you.

Rashesh Bosamiya
  • 609
  • 1
  • 9
  • 13
  • I've set font to System in storyboard, I'm setting font and textColor properties to nil and then I set attributedText, but issue still persists. It seems like the only way to do this is to call this in DispatchQueue.main.async but you can see a short flash of wrong text colour. – Makalele Mar 08 '19 at 10:53