HomeiOS DevelopmentSwiftUI TabView (.web page / PageTabViewStyle) choice can get out of sync...

SwiftUI TabView (.web page / PageTabViewStyle) choice can get out of sync when person interrupts a programmatic web page change


SwiftUI TabView with .web page type appears to permit person interplay to interrupt an in-flight web page transition, leaving the UI in an inconsistent state.

Anticipated: the seen web page all the time matches the certain choice.
Noticed: if the person faucets/drags the pager throughout a programmatic web page change, the certain choice updates, however the seen web page can stay the earlier one. After that, subsequent web page modifications can “bounce” (e.g. two pages at a time), as a result of the visible web page and choice have diverged.

Here’s a GIF displaying the problem:

SwiftUI TabView (.web page / PageTabViewStyle) choice can get out of sync when person interrupts a programmatic web page change

Within the GIF, I begin with choice = 5 and web page “Web page 5” seen. I faucet Prev after which work together with the pager mid-transition. The seen web page stays “Web page 5”, however the mannequin has up to date (choice = 4). Tapping Prev once more then animates two pages to succeed in “Web page 3”, which suggests the pager’s inside state is now out of sync with the binding.

Repro steps:

  1. Run the minimal reproducible instance beneath.
  2. Faucet Prev or Subsequent to vary choice.
  3. Whereas the web page transition remains to be in progress, shortly faucet/drag on the pager.
  4. Observe that choice modifications however the seen web page generally doesn’t.

Minimal reproducible instance

struct Web page: View {
    let index: Int

    var physique: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 24)
                .fill(Shade(white: 0.92))
                .padding(24)

            Textual content("Web page (index)")
                .font(.system(measurement: 48, weight: .daring, design: .rounded))
        }
    }
}

struct PagerDesyncReproView: View {
    @State personal var choice: Int = 0
    personal let pageCount = 6

    var physique: some View {
        VStack(spacing: 0) {
            HStack(spacing: 12) {
                Button("Prev") {
                    guard choice > 0 else { return }
                    choice -= 1
                }
                .buttonStyle(.bordered)

                Button("Subsequent") {
                    guard choice < pageCount - 1 else { return }
                    choice += 1
                }
                .buttonStyle(.borderedProminent)

                Spacer()

                Textual content("choice = (choice)")
                    .font(.system(.caption, design: .monospaced))
                    .foregroundStyle(.secondary)
            }
            .padding(.horizontal)

            TabView(choice: $choice) {
                ForEach(0..<pageCount, id: .self) { i in
                    Web page(index: i)
                        .tag(i)
                }
            }
            .animation(.default, worth: choice)
            .transition(.slide)
            .tabViewStyle(.web page(indexDisplayMode: .all the time))
            .body(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

Is there a supported strategy to forestall this desynchronization (e.g. disable interplay till the web page transition completes), or to detect cancellation/completion of the web page transition so the binding might be stored constant?

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments