【Swift】UIButtonをsetTitleしたときのちらつきをなくす


はじめに

以下のように、UIButtonをsetTitleした時に一瞬ちらついてしまいます。これをスムーズに入れ替える方法を紹介します。

ちらつきあり

ちらつきなし

実装

まず、ちらつきをなくす前のコードがこちらです。 

enum ButtonType {
    case a
    case b
    var text: String {
        switch self {
            case .a: return "AAAAA"
            case .b: return "BBBBB"
        }
    }
    mutating func change() {
        switch self {
            case .a: self = .b
            case .b: self = .a
        }
    }
}

final class ViewController: UIViewController {

    @IBOutlet private weak var button: UIButton!
    private var buttonType: ButtonType = .b

    @IBAction private func buttonDidTapped(_ sender: Any) {
        button.setTitle(buttonType.text, for: .normal)
        buttonType.change()
    }

}

そして、ちらつきをなくしたコードがこちらです。

enum ButtonType {
    case a
    case b
    var text: String {
        switch self {
            case .a: return "AAAAA"
            case .b: return "BBBBB"
        }
    }
    mutating func change() {
        switch self {
            case .a: self = .b
            case .b: self = .a
        }
    }
}

final class ViewController: UIViewController {

    @IBOutlet private weak var button: UIButton!
    private var buttonType: ButtonType = .b

    @IBAction private func buttonDidTapped(_ sender: Any) {
        UIView.setAnimationsEnabled(false)
        button.setTitle(buttonType.text, for: .normal)
        buttonType.change()
        button.layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }

}

ポイントは以下ですね。
ボタンのタイトルを変更する前にアニメーションを止めて、ちらつきを無くします。そして、ボタンに対してlayoutIfNeededをしてあげることで、ちらつきがなくなります。(これを書かないと、ちらついてしまう)そして、最後にアニメーションを再開します。

UIView.setAnimationsEnabled(false)
button.setTitle(buttonType.text, for: .normal)
buttonType.change()
button.layoutIfNeeded()
UIView.setAnimationsEnabled(true)

おわりに

おわりです。