0

I have a situation that I have to update a child view within a view that is under an onging transition.

Here is a simple code to reproduce/demonstrate the issue I just mentioned.

struct ContentView: View {
    @State var text = "\(Date().timeIntervalSince1970)"
    @State var isOn = true

    var body: some View {
        ZStack {
            VStack {
                if isOn {
                    Image(systemName: "globe")
                        .imageScale(.large)
                        .foregroundColor(.accentColor)

                    Text(text)
                        .transition(.move(edge: .bottom))
                }
            }
            .zIndex(1)
            .animation(.default, value: isOn)

            Color.clear
                .ignoresSafeArea()
                .overlay(alignment: .bottom) {
                    Button("Click") {
                        isOn.toggle()
                        text = isOn ? "\(Date().timeIntervalSince1970)" : "Hello, Swift!"
                    }
                }
        }
    }
}

In the above code, I have a Text which will be hidden/shown by clicking the bottom button. And update the text to a different value when it shows up next time.

If I click the button quickly, which means the text is updated before the transition finished. Then the text loses the transition and shows up directly at the "final" position.

How to updating a child view during transition? Or there is a limitation on SwiftUI for now?

mrfour
  • 1,128
  • 12
  • 21
  • What do you want to happen instead? – Sweeper Aug 22 '23 at 07:49
  • I want the `Text` still move smoothly by the transition effect. It's ok for me that `Text` has a fade transition to update the text. In my real case, this is inside a bottom sheet like style, so I the the text "moved" along with the sheet even its text is updated. – mrfour Aug 22 '23 at 08:31

1 Answers1

0

You could try using a .debounce(...) to add a delay to the isOn within a ObservableObject

class Dmodel: ObservableObject {
    @Published var text = "\(Date().timeIntervalSince1970)"
    @Published var isOn = true
    
    init() {
        $isOn.debounce(for: .seconds(0.8), scheduler: RunLoop.main)
    }
}

struct ContentView: View {
    @StateObject var modl = Dmodel()

    var body: some View {
        ZStack {
            VStack {
                if modl.isOn {
                    Image(systemName: "globe")
                        .imageScale(.large)
                        .foregroundColor(.accentColor)

                    Text(modl.text)
                        .transition(.move(edge: .bottom))
                }
            }
            .zIndex(1)
            .animation(.default, value: modl.isOn)

            Color.clear
                .ignoresSafeArea()
                .overlay(alignment: .bottom) {
                    Button("Click") {
                        modl.isOn.toggle()
                        modl.text = modl.isOn ? "\(Date().timeIntervalSince1970)" : "Hello, Swift!"
                    }
                }
        }
    }
}