【SwiftUI 3.0】Self._printChanges で View の再描画を監視する

View の body の中に Self._printChanges() を組み込むと、その View の再描画のトリガーとなった状態変数(@State 等)を出力してくれます。

想定外の再描画のきっかけがわからない時などのデバッグに役立つでしょう。

動作確認環境

macOS Monterey(12.2.1)

Xcode 13.2.1

iOS 15.2(iPhone 13 mini シミュレータ)

【SwiftUI 3.0】Self._printChanges で View の再描画を監視する

Self._printChanges() の使用例

Toggle ボタンと List を配置したサンプルです。

struct Todo: Identifiable, Hashable {
    let id = UUID().uuidString
    let title: String
    let description: String
}

struct ContentView: View {
    
    @State private var isOn = false
    @State private var todos = [Todo]()
    
    var body: some View {
        let _ = Self._printChanges()
        VStack {
            Toggle(isOn ? "ONです" : "OFFです", isOn: $isOn)
            List(todos, id: \.self) { todo in
                VStack(alignment: .leading) {
                    Text(todo.title).font(.title2)
                    Text(todo.description)
                }
            }
        }
        .padding()
        .task() {
            fetchTodos()
        }
    }
    
    func fetchTodos() {
        todos = [
            Todo(title: "やることその1", description: "やることその1の内容です。"),
            Todo(title: "やることその2", description: "やることその2の内容です。"),
            Todo(title: "やることその3", description: "やることその3の内容です。"),
            Todo(title: "やることその4", description: "やることその4の内容です。"),
            Todo(title: "やることその5", description: "やることその5の内容です。")
        ]
    }
}
実行画面

var body: some View の先頭で Self._printChanges をコールしています。

「let _ =」としているのはビルドエラーを回避するためです(body の中で戻り値 void の関数を呼べないため)

var body: some View {
    let _ = Self._printChanges()

上記のサンプルでは、初回の読み込み時の task 内で todos をセットするタイミングと、Toggle ボタンを ON/OFF する度にデバッグコンソールに出力されます

「(対象のView名): _状態変数名 changed」という形式出力されていることがわかります。

@StateObject@Published でも同じように出力してくれます

注意点

あくまでデバッグ目的の機能でユーザーには何のメリットもありません

リリースビルドのコードには含まれるべきではないため、そのままだとリジェクトされる可能性があります実際に試した訳ではないのでご存じの方はコメント頂けると幸いです)。

#if DEBUG〜#endif 等でリリースビルド時に除外されるようにしておくと良いかもしれません。

var body: some View {
#if DEBUG
    let _ = Self._printChanges()
#endif

以上