Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OnAppear calls unexpectedly when Keyboard Appears in SwiftUI

I am experiencing very odd behavior in SwiftUI 2.0 and iOS14.

When the keyboard appears on the screen, the OnAppear method of other tab's view called automatically.

However, this works fine Xcode 11.7

Here is the issue in action. TextField In TabView

Here is the code which produces the above error.

struct ContentView: View {
    var body: some View {
        TabView {
            DemoView(screenName: "Home")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("Home")
                }
            DemoView(screenName: "Result")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("Result")
                }
            DemoView(screenName: "More")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("More")
                }
        }
    }
}

struct DemoView:View {
    
    @State var text:String = ""
    var screenName:String
    var body: some View {
        VStack{
            Text(screenName)
                .font(.title)
            
            TextField("Buggy Keyboard Issue", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                
            Text("Issue : When keyboard appears, onAppear of other 2 tabs call automatically.")
                .font(.footnote)
        }
        .padding()
        .onAppear(perform: {
            debugPrint("OnAppear of : \(screenName)")
        })
    }
}

This seems to be a bug of SwiftUI 2.0 but not sure. Any help will be appreciated.

Thanks

like image 744
Malav Soni Avatar asked Sep 06 '25 03:09

Malav Soni


2 Answers

Having the same issue myself, I think this is a bug or something like that, however I came up with a solution maybe a workaround until apple will fix it.

The thing that I did is basically I used a LazyVStack, and this seems to be working perfectly.

LazyVStack {
    VStack{
        Text(screenName)
            .font(.title)
        
        TextField("Buggy Keyboard Issue", text: $text)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            
        Text("Issue : When keyboard appears, onAppear of other 2 tabs call automatically.")
            .font(.footnote)
    }
    .padding()
    .onAppear(perform: {
        debugPrint("OnAppear of : \(screenName)")
})
}

Now the OnAppear method of other tab's view it is not called automatically when the keyboard appear.

Solution

like image 134
Cod3rMax Avatar answered Sep 07 '25 21:09

Cod3rMax


Just implemented the following workaround:

struct ContentView: View {
    var body: some View {
        TabView(selection: $selectedTab) {
            TabContentView(tag: 0, selectedTag: selectedTab) {
                Text("Some tab content")
            }
            .tabItem {
                Text("First tab")
            }
            TabContentView(tag: 0, selectedTag: selectedTab) {
                Text("Another tab content")
            }
            .tabItem {
                Text("Second tab")
            }
        }
    }
    
    @State private var selectedTab: Int = 0
}

private struct TabContentView<Content: View, Tag: Hashable>: View {
    init(tag: Tag, selectedTag: Tag, @ViewBuilder content: @escaping () -> Content) {
        self.tag = tag
        self.selectedTag = selectedTag
        self.content = content
    }

    var body: some View {
        Group {
            if tag == selectedTag {
                content()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            } else {
                Color.clear
            }
        }
        .tag(tag)
    }

    private let tag: Tag
    private let selectedTag: Tag
    private let content: () -> Content
}

Not sure if it's stable enough but keyboard appearance doesn't trigger onAppear on tabs content anymore.

like image 33
Mark Kotevode Avatar answered Sep 07 '25 19:09

Mark Kotevode