Search code examples
swiftuifocustabviewios16

Swiftui Focus Field in TabView


I'm using TabView to display a scrollable tab list of players to update. I am trying to focus the newScoreEntry field upon scrolling to the next TabView. I am having trouble figuring out how to focus the right field based upon my selectedTab. I think I have to somehow define my focusfield as an array of fields or something?

struct ScoreRoundView: View {
@StateObject var game: Game
@State var newScoreEntry: [String] = Array(repeating: "", count: 50)
@State var selectedTab = 0

@FocusState private var focusScore: Bool

var body: some View {
        TabView(selection: $selectedTab) {
            ForEach(Array(zip(game.playersArray.indices, game.playersArray)), id: \.1) { i, player in            
                    TextField("Round Score", text: $newScoreEntry[i])
                            .focused($focusScore)
                }.tag(i)
            }
        }
        .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
        .onChange(of: selectedTab, perform: { value in
            focusScore = true
        })
    }
}

Solution

  • I figured out what i was looking for, so i thought i would post the solution. I had to use focusable field with an id associated with it.

    enum Focusable: Hashable {
      case tabView(id: Int)
    }
    
    @FocusState var focusedField: Focusable?
    
    @StateObject var game: Game
    @State var newScoreEntry: [String] = Array(repeating: "", count: 50)
    @State var selectedTab = 0    
    
    var body: some View {
            TabView(selection: $selectedTab) {
                ForEach(Array(zip(game.playersArray.indices, game.playersArray)), id: \.1) { i, player in
    
                        TextField("Round Score", text: $newScoreEntry[i])
                                .focused($focusedField, equals: .tabView(id: i))
                    }.tag(i)
            }
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
            .onChange(of: selectedTab, perform: { value in
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                    self.focusedField = .tabView(id: value)
                }
            })