Alessio Raddi
Alessio Raddi

Reputation: 622

Keyboard bug when tapping on TextField in SwiftUI

I have a Main View that contains multiple Views and picks one based on the value change of a variable in a ObservabledObject, which change on buttons press.

The problem comes when I select a View that contains input fields, in that case, when I tap on a TextField, instead of showing the keyboard, it takes me back to the Homepage View.

It only happens on devices, not on simulators.

Though, it works if you set that specific view (the one with TextField) as Main View (the first case in the Switch).

Here's the ObservableObject Code:

class Watcher : ObservableObject {
    @Published var currentView: String = "home"
}

Main View:

import SwiftUI

struct MainView : View {
    var body: some View {
        
        GeometryReader { geometry in
            ZStack (alignment: .leading){
                HomepageView()
                    .frame(width: geometry.size.width, height: geometry.size.height)
            }
        }
    }
}

struct HomepageView : View {
    @ObservedObject var watcher = Watcher()
    
    init(){
        UITabBar.appearance().isHidden = true
        JSONHandler.fetchData(webService: "https://myWebsite.com/app/request.php") {
            print("loaded")
        }
    }
    
    var body: some View {
        ZStack {
            VStack {
                TabView {

                    switch self.watcher.currentView {
                    case "home":                                       //STARTING CASE
                        NavigationView {
                            DailyMenuView()
                                .navigationTitle("Recipes APP")
                                .navigationBarTitleDisplayMode(.inline)
                        }
                        .opacity(self.watcher.currentView == "newRecipe" ? 0 : 1)

                    case "innerMenu":
                        InnerMenuView(watcher: watcher)

                    case "members":
                        MembersView(watcher: watcher)

                    case "recipe":
                        RecipeView(watcher: watcher)

                    case "newRecipe":                                  //TextField View
                        TestView()

                    default:
                        Text("Error")
                    }
                }
            }
            
            VStack {
                Spacer()
                
                MenuTabView(watcher: watcher)
            }                
            .edgesIgnoringSafeArea(.bottom)
            
        }
        .environment(\.colorScheme, self.watcher.currentView == "home" ? .dark : .light)
        
    }
}

struct MainView_Previews: PreviewProvider {
    static var previews: some View {
        MainView()
    }
}

And last, the View containing TextField:

import SwiftUI

struct TestView: View {
    @State var text: String = ""
    
    var body: some View {
        VStack {
            Text("TEST VIEW")
                .font(.largeTitle)
                .fontWeight(.bold)
            
            Spacer()
            
            TextField("Write here", text: $text)
                .font(.title)
                .padding()
                .border(Color.red, width: 2)
            
            Spacer()
        }
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

Hope you can help me solve this mess!

If you need more information, ask me.

Upvotes: 1

Views: 561

Answers (2)

Alessio Raddi
Alessio Raddi

Reputation: 622

I solved moving:

@ObservedObject var watcher = Watcher()

Inside the Main View as it follows:

struct MainView : View {
    @ObservedObject var watcher = Watcher()

    var body: some View {            
        GeometryReader { geometry in
            ZStack (alignment: .leading){
                HomepageView()
                    .frame(width: geometry.size.width, height: geometry.size.height)
            }
        }
    }
}

Upvotes: 0

Raja Kishan
Raja Kishan

Reputation: 18904

You need to use tag and selection.

TabView(selection: $watcher.currentView) { // < === Here
    
    switch self.watcher.currentView {
    case "home":                                       //STARTING CASE
        NavigationView {
            DailyMenuView()
                .navigationTitle("Recipes APP")
                .navigationBarTitleDisplayMode(.inline)
        }
        .opacity(self.watcher.currentView == "newRecipe" ? 0 : 1)
        .tag("home") // < === Here
        
    case "innerMenu":
        InnerMenuView(watcher: watcher)
            .tag("innerMenu") // < === Here
    case "members":
        MembersView(watcher: watcher)
            .tag("members") // < === Here
        
    case "recipe":
        RecipeView(watcher: watcher)
            .tag("recipe") // < === Here
    case "newRecipe":                                  //TextField View
        TestView()
            .tag("newRecipe") // < === Here
        
    default:
        Text("Error")
    }
}

Upvotes: 1

Related Questions