1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

iOS13 で UILabel のスタイルが間違えて表示されている可能性がある

Posted at

起きたこと

UILabel の attributedText を nil (リセット) にしてもラベルのスタイルが変わらないという現象が発生していました。

image.png

TL;DR

原因

UILabel の attributedText の値が nil(リセット)になった場合、通常(iOS12以前)は Label の attributes もリセットされるが iOS13 ではリセットされないとの報告があり、それが起因して考えられます。

解決策

UILabel の textattributedText はどちらか一方の値が変わるともう一方の値も変わるという連動性があることから(下記ドキュメント)、今回のように textattributedText を共存させて更新することはシステムのバグに限らず望ましくないので、attributedText のみ明示的に更新処理を行うように修正したところ解決しました。

  • [https://developer.apple.com/documentation/uikit/uilabel/1620542-attributedtext:title]

  • [https://developer.apple.com/documentation/uikit/uilabel/1620538-text:title]

※ iOS13のバグかどうかについては現在のところ不明

具体的な発生タイミングと改善

Before

チャットに表示する UI で、コメントがリンクの場合は青く表示させて Clickable にさせるように UILabel を継承したサブラクス(以降: LinkLabel)を作成していました。基本的な仕様としては LinkLabel の text プロパティに didSet をセットし、更新されたタイミングでテキストをトリミングして attributedText を更新するという感じです。

final class LinkLabel: UILabel {
    override var text: String? {
        didSet {
            updateAttributedText()
        }
    }

    func updateAttributedText() {
        guard let text = text else {
            return
        }
        let mutableAttributedString = NSMutableAttributedString(string: text)

        // 省略....
        // いろいろ Attributes をセットする

        attributedText = mutableAttributedString
    }
}

上記で作成した LinkLabel を Cell に配置して TableView で表示した時に、Cell が再利用されるタイミングで以前の attributes がキャッシュされていて関係ないコメントも青く表示されることがたびたび起こるようになりました。

After

TL;DR にも記載してある通り、attributedText だけを明示的に更新することで改善できたので下記のように修正します。

final class LinkLabel: UILabel {
    var displayText: String?

    func setText(_ text: String?) {
        displayText = text
        updateAttributedText()
    }

    func updateAttributedText() {
        guard let text = displayText else {
            return
        }
        let mutableAttributedString = NSMutableAttributedString(string: text)

        // 省略....
        // いろいろ Attributes をセットする

        attributedText = mutableAttributedString
    }
}

使用する Cell 側でもキャッシュをリセットできるように prepareForReuse() セットします

final class CommentCell: UITableViewCell {
    let linkLabel = LinkLabel()

    override func prepareForReuse() {
        super.prepareForReuse()
        linkLabel.attributedText = nil
    }

    // 省略...
}

調べたこと

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?