iOSアプリの画面表示が更新されないという、スレッドかUIの描画タイミングに問題がありそうなふるまいなのに実は named color が原因という手強い問題がありました
現象
発生していたのは UITableViewCell
と UITableViewHeaderFooterView
の subview の backgroundColor
が更新されないという現象でした。
補足
- Cell を一度画面外に出してから再度画面内にスクロールしてきたり、時間差を置いて
reloadData()
を呼び出すなどすれば正常にbackgroundColor
が更新されます。 -
backgroundColor
を設定している行でブレークすると正常に代入されていることを確認できるものの、実行を再開して Debug View Hierarchy などで再度確認すると Interface Builder で設定した色に戻っています - iOS12で再現し、iOS13では発生しません
- Interface Builder で設定する色が named color でなければ発生しません
原因
こちらの方が調べていますが、UIKitが layoutSubviews()
時に named color を別オブジェクトに変換して再度 backgroundColor
に設定するという挙動をするため、初回の layoutSubviews()
以前に backgroundColor
に設定した値が無視されているということです
https://stackoverflow.com/a/59145038/3890662
対策
layoutSubviews()
以降のタイミングで backgroundColor
を設定すればOKです
UITableViewCell
の場合
backgroundColor
の設定を tableView(_: willDisplay: forRowAt:)
で行うことで回避できます
UITableViewHeaderFooterView
の場合
backgroundColor
の設定を layoutSubviews()
で行うことで回避できます
補足
-
layoutSubviews()
は IBOutlet の設定 前 にも呼び出されるので注意が必要です -
tableView(_: willDisplayHeaderView: forSection:)
を利用しても 解決しません- これは単純に delegate メソッドが呼び出されるタイミングの問題だと思います