0

I am using a SplitViewController; The master is tableView with a series of RightDetail cells whose Attributed Strings are set via a callback from a value setting popover.

The value passed back and set via a method that sets the detailTextLabel of the cell. It does this within a DispatchQueue.main.async as some of updates to detailTextLabel are made via calls from Network.Framework

The strange thing is when the popover makes the changes the change to the attributed string is not presented correctly. The focus has to change to the next table cell before the correct drawing occurs.

enter image description here

So it is only when focus changes to "Flow Rate" that temperature is rendered correctly, as shown blow.

enter image description here

I have stepped through the following code and checked that the correct value is being written to self.buttonCell?.detailTextLabel?.attributedText

You'll also see that I've added setNeedsLayout() and setNeedsFocusUpdate()

func setDetailValueWithUnit( to index: Int) {
    /** sets the detailtext to the value as the specified index and appends units.
        it does this within the main dispatchQueue as this method is called by
        operationResult which is called by the statemachine.
     **/
    DispatchQueue.main.async {
        let font = self.buttonCell?.detailTextLabel?.font
        let finalString = NSMutableAttributedString(string: valueString,attributes: [.font:font!])

        if let units = self.units() {
            finalString.append(units)
            self.buttonCell?.detailTextLabel?.attributedText = finalString

            //next 2 lines experimental in an attempt to fix the attributed text not
            //being consistently redendered correctly
            self.buttonCell?.detailTextLabel?.setNeedsLayout()
            self.buttonCell?.detailTextLabel?.setNeedsFocusUpdate()
            NSLog("setDetailValueWithUnit: %d", index)
            return
        } else {
            assert(false, "No Units found")
        }
    }
}
eklektek
  • 1,083
  • 1
  • 16
  • 31

1 Answers1

1

The problem is that what you are doing is completely wrong. You should never be touching a cell's text label font, text, or anything else directly like that. That's not how a table view works. You should set the table's data model and update the table from there, thus causing cellForRowAt: to be called for the visible cells. In that way, only cellForRowAt: configures the cell, and all will be well.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • thanks for the response. This is a static table, if that makes any difference (probably not). Sorry I am probably missing something as to my knowledge I don't change the font I simply read it so that I can use the same on the "finalString" which is then used to set the "attributedText", guess that make no difference! I'd better do some research on models applied to Static tables. Thanks for the guidance. – eklektek Aug 17 '19 at 17:40
  • "This is a static table" I believe your own example proves that it is not. It is the opposite of a static table. Its content can change so it is a dynamic table. Nothing about my answer changes. Tables do not store data! They _reflect_ data. – matt Aug 17 '19 at 18:11
  • it’s on the story board as static, but the data isn’t! - point taken - thanks. – eklektek Aug 17 '19 at 18:16
  • 1
    I am saying that, knowing the data would change, you should never have made this a static table in the storyboard to begin with. You need a data model object, so making this table "static" is pointless. You _could_ keep it as static but you would _still_ need to do what I said: change the _model_ and reload the data so that `cellForRowAt:` is called. – matt Aug 17 '19 at 18:35
  • Yup my code needs refactoring & your not going to like this, however prompted somewhat by your attention to the cell rather than its labels I tried the following which fixed the issue: self.buttonCell?.setNeedsLayout(). Think you just found another customer for your publications. Appreciated the wisdom. – eklektek Aug 18 '19 at 13:26