11

I'm trying to make a tabbed application on macOS with SwiftUI, and I have an odd issue with TabView.

When I have two tabs with TextFields each and save their text states to their respective private variables, something odd happens: When I switch from tab A to tab B after entering text into tab A's TextField, the tab indicator shows that I am still on tab A, but the content shows tab B's content. When I click on the button for tab B once again, it will still show tab B's content. Furthermore, when I press the button for tab A afterward, it will show the content of tab A, but the indicator for the tab still shows that I am on tab B.

What might I possibly be doing wrong?

Here is an example that illustrates my issue:

import SwiftUI

struct ContentView: View {
    var body: some View {
        TabView
            {
                TabAView()
                    .tabItem({Text("Tab A")})
                TabBView()
                    .tabItem({Text("Tab B")})
        }
    }
}

struct TabAView: View {
    @State private var text = ""
    var body: some View {
        VStack{
            Text("Tab A")
            TextField("Enter", text: $text)
        }
    }
}

struct TabBView : View {
    @State private var text = ""
    var body: some View {
        VStack {
            Text("Tab B")
            TextField("Enter", text: $text)
        }
    }
}

Here's a screen capture of the issue occurring: And here is a GIF of the issue occurring

chungmcl
  • 310
  • 1
  • 3
  • 14
  • 3
    Your code is correct, so you can submit a bug to Apple. – Asperi Dec 23 '19 at 06:38
  • 2
    Agree with @Asperi. I tried providing `TabView` with a selection binding and tags on each `tabItem`, but the issue persists. Seems like a bug. – Austin Dec 23 '19 at 06:55
  • I submitted a bug report to Apple in December of 2019, and I just got a response today. They asked me to check if the issue still persisted in the latest build Version 11.4 (11E146), and sure enough -- it's still there. I sent them a new screen recording and source code. I will update when and if they respond again. – chungmcl Apr 02 '20 at 21:11
  • Seeing this exact issue as well, makes tabs unusable - sometimes it also displays two or even three tabs over each other as well. – lupinglade May 10 '20 at 03:41
  • @lupinglade Glad(?) to hear that I'm the only one dealing with this. They actually responded and asked me to send them another report if I experienced the issue again in the latest build (which I did) but they haven't responded since. Have you made a report yourself? – chungmcl May 15 '20 at 08:13
  • @chungmcl facing the same issue. Did you try Xcode 11.5 to see if it fixed it? Were you able to come up with a workaround? – pgb May 20 '20 at 20:26
  • @pgb Just tried it with 11.5; it doesn't seem to have been fixed. I'd highly suggest anyone else who is dealing with this issue submit a bug report via the Feedback Manager app. They responded to me once simply telling me to re-send them feedback if I was still dealing with the issue, and I did, but they have yet to respond. I haven't found any workarounds unfortunately. – chungmcl May 21 '20 at 04:06
  • I experience exactly the same! I've tried a couple of things but nothing helped so far. Will send a bug report asap. – Flo Ragossnig May 23 '20 at 16:31
  • I seem to have had the same problem: https://stackoverflow.com/questions/61009837/why-does-color-used-as-aswiftui-zstack-background-not-update-on-tabview-on-a I've not found a solution yet. Oddly, the simulator works, but not a real device. – Rillieux May 24 '20 at 14:20
  • Interesting! Please let me know me you guys get a response from Apple. – chungmcl May 27 '20 at 07:14

1 Answers1

4

This is definitely a bug in SwiftUI's implementation of TabView. But you can easily work around the problem by binding to TabView selection and setting the current tab manually like so:

struct ContentView: View {
    @State private var currentTab = 0
    var body: some View {
        TabView(selection: $currentTab)
            {
                TabAView()
                    .tabItem({Text("Tab A")})
                    .tag(0)
                    .onAppear() {
                        self.currentTab = 0
                    }
                TabBView()
                    .tabItem({Text("Tab B")})
                    .tag(1)
                    .onAppear() {
                        self.currentTab = 1
                    }
        }
    }
}

This bug only seems to manifest itself when the user changes tabs while a TextField has focus.

If you make the above changes to your code, it will work as expected.

Screen capture of fix working

  • Thank you for your response! I'll go ahead and try this; definitely seems like it will work for the time being. I still haven't gotten a response from Apple since the last time I contacted them again so hopefully they will put up a bug fix soon. – chungmcl Jun 18 '20 at 01:09
  • So glad I found this, because it's still happening in macOS. – Yung Dai Mar 01 '21 at 19:44
  • good lord, this is still happening on iOS now in June 2023, 3 years later. This fix however doesn't solve the problem for me. When the TabView is initialised to anything other than the 1st tab at app launch, the visual is for the correct tab, but the page indicator is for the 1st tab, so manually navigating to the first does nothing because the TabView thinks it's already there. – PKCLsoft Jul 09 '23 at 00:27