Skip to content

Instantly share code, notes, and snippets.

@omochi
Created August 17, 2025 00:39
Show Gist options
  • Select an option

  • Save omochi/967fc25720e389043bfe85e420f480c9 to your computer and use it in GitHub Desktop.

Select an option

Save omochi/967fc25720e389043bfe85e420f480c9 to your computer and use it in GitHub Desktop.
@omochi
Copy link
Author

omochi commented Aug 17, 2025

import SwiftUI
import Observation

@Observable
final class Controller {
    init() {}

    var showsAlert: Bool = false
    var step: Int = 0
    var buttonCount: Int = 0
}

struct ContentView: View {
    @State var controller: Controller = .init()

    var body: some View {
        VStack {
            Button("tap me") {
                controller.step = 1
                controller.buttonCount = 0
                controller.showsAlert = true
            }
        }
        .padding()
        .alert(
            "alert",
            isPresented: $controller.showsAlert,
            presenting: controller.step,
            actions: { _ in
                Button("OK") {
                    controller.buttonCount += 1
                }
            },
            message: {
                Text("\($0)")
            }
        )
        .onChange(of: controller.showsAlert) { _, _ in
            update()
        }
        .onChange(of: controller.buttonCount) { _, _ in
            update()
        }
    }

    func update() {
        guard controller.showsAlert == false else { return }
        guard controller.step <= 5 else { return }
        guard controller.buttonCount == controller.step else { return }

        print(controller.showsAlert, controller.step, controller.buttonCount)
        controller.step += 1
        controller.showsAlert = true
    }
}

@omochi
Copy link
Author

omochi commented Aug 17, 2025

ちょっと遅らせると動く・・・

    func update() {
        guard controller.showsAlert == false else { return }
        guard controller.step < 10 else { return }
        guard controller.buttonCount == controller.step else { return }

        print(controller.showsAlert, controller.step, controller.buttonCount)

        controller.step += 1

        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
            controller.showsAlert = true
        }
    }

@Kyome22
Copy link

Kyome22 commented Aug 17, 2025

なんと、withAnimationのcompletionを使えば完全に動くっぽいです。Simulatorのスローアニメーションにしても動きました。

    func update() {
        guard controller.showsAlert == false else { return }
        guard controller.step <= 5 else { return }
        guard controller.buttonCount == controller.step else { return }

        print(controller.showsAlert, controller.step, controller.buttonCount)
        withAnimation {
            controller.step += 1
        } completion: {
            controller.showsAlert = true
        }
    }

↓ではダメ。

withAnimation {
    //
} completion: {
    controller.step += 1
    controller.showsAlert = true
}

@omochi
Copy link
Author

omochi commented Aug 17, 2025

現状、update()を呼ぶ経路が2つあるので、stepは即座に更新しないと色々おかしくなりますね。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment