Home > Back-end >  SwiftUI TabView PageStyle with an optional page
SwiftUI TabView PageStyle with an optional page

Time:10-03

In SwiftUI, I want that the state of the first page of a TabView determines if the second page is rendered or does not exist at all.

Complete example code:

import SwiftUI

struct OptionalPageTabView2: View {
    @ObservedObject var model = TabViewModel.shared
    var body: some View {
        TabView {
            let _ = print("rendering TabView")
            Toggle(isOn: $model.on) {
                Text("Show second page")
            }
            //if model.on {
                Page2View()
            //}
            Text("Hello third page")
        }
        .tabViewStyle(.page)
        .indexViewStyle(.page(backgroundDisplayMode: .always))
    }
}

struct Page2View: View {
    @ObservedObject var model = TabViewModel.shared
    var body: some View {
        let _ = print("rendering second page, secondPageState:\(model.on)")
        if model.on {
            Text("Hello second page on")
        } else {
            //Text("Hello second page off")
            EmptyView()
        }
    }
}

class TabViewModel: ObservableObject {
    static let shared = TabViewModel()
    private init(){}
    @Published var on: Bool = true
}

struct OptionalPageTabView_Previews: PreviewProvider {
    static var previews: some View {
        OptionalPageTabView2()
    }
}

Test 1:

  • start example
  • verify console shows something like

rendering TabView rendering second page, secondPageState:true 2021-10-02 11:34:06.700231 0200 TabTest2[4708:100634] [UICollectionViewRecursion] cv == 0x7fb94c01fa00 Disabling recursion trigger logging

  • verify that the index has 3 dots
  • scroll through 3 pages
  • go to the first page again
  • turn off the toggle
  • verify that the console shows something like

rendering TabView rendering second page, secondPageState:false

  • verify that the index has 2 dots

expected: TabView shows 2 pages

problem: TabView shows the original 3 pages

Test 2:

  • start example
  • verify console shows something like

rendering TabView rendering second page, secondPageState:true 2021-10-02 11:34:06.700231 0200 TabTest2[4708:100634] [UICollectionViewRecursion] cv == 0x7fb94c01fa00 Disabling recursion trigger logging

  • verify that the index has 3 dots
  • turn off the toggle
  • verify that the console shows something like

2021-10-02 11:41:45.968083 0200 TabTest2[4838:106887] invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution. rendering TabView rendering second page, secondPageState:false

  • scroll
  • verify that the second page is empty
  • go back to the first page
  • turn on the toggle
  • scroll

expected: Second page shows text

problem: Second page is empty

What can I do that the second page is shown or not shown, depending on the state (change) of the first page? What can I do that the second page updates depending on the state change of the fist page?

(Replacing TabView with List shows a list where the second list item is shown depending on the state of the first list item)

Xcode 13, iOS Target 14.0

CodePudding user response:

Force refresh tab view by .id

TabView {
    .......
    .......
}.id(model.on)
  • Related