最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Text field not being focused in SwiftUI sheet on macOS - Stack Overflow

programmeradmin1浏览0评论

I'm using SwfitUI with macOS. I have two text fields in a sheet, a Picker and a TextField. I want the second TextField to have focus when a boolean is set if the Picker only has a single element (because there's nothing to choose). Below, please find simplified code where I'm always setting focusRoadNameField to true. I'm then using this @FocusState variable with focused() on the TextField—but the picker is still always being focused when the sheet opens.

import AppKit
import SwiftUI

struct ContentView: View {
    @State private var sheetOpen: Bool = false
    @State private var roadName: String = ""
    @State private var noFocus: String = ""
    
    @FocusState private var focusRoadNameField: Bool

    var body: some View {
        Button(action: {
            sheetOpen = true
            roadName = ""
            
            // And yet the field isn't focused
            focusRoadNameField = true
        }) {
            Text("Open Sheet")
        }
        .sheet(isPresented: $sheetOpen, content: {
            VStack {
                TextField("No focus", text: $noFocus)

                TextField("Road Name", text: $roadName)
                    .focused($focusRoadNameField)
                
                HStack {
                    Button("Cancel", action: {
                        sheetOpen = false
                    }).keyboardShortcut(.cancelAction)
                    .padding()

                    Spacer()

                    Button("Add Road", action: {
                        print("=> Add road '\(roadName)'")
                        sheetOpen = false
                    }).keyboardShortcut(.defaultAction)
                    .padding()
                }
            }
            .frame(width: 260)
            .padding()
        })
        .frame(width: 100, height: 50)
    }
}

#Preview {
    ContentView()
}

Update: Thanks to Sweeper for the comment. I forgot that I am using Full Keyboard Access, so widgets like the Picker get keyboard focus with a focus ring. I've adjusted the example to use two text fields to show the buggy behavior even on systems which don't have Full Keyboard Access enabled, which is the default state.

Now, you will see the sheet always open with the first, "No focus" field selected, despite the second field having the .focused() modifier.

I'm using SwfitUI with macOS. I have two text fields in a sheet, a Picker and a TextField. I want the second TextField to have focus when a boolean is set if the Picker only has a single element (because there's nothing to choose). Below, please find simplified code where I'm always setting focusRoadNameField to true. I'm then using this @FocusState variable with focused() on the TextField—but the picker is still always being focused when the sheet opens.

import AppKit
import SwiftUI

struct ContentView: View {
    @State private var sheetOpen: Bool = false
    @State private var roadName: String = ""
    @State private var noFocus: String = ""
    
    @FocusState private var focusRoadNameField: Bool

    var body: some View {
        Button(action: {
            sheetOpen = true
            roadName = ""
            
            // And yet the field isn't focused
            focusRoadNameField = true
        }) {
            Text("Open Sheet")
        }
        .sheet(isPresented: $sheetOpen, content: {
            VStack {
                TextField("No focus", text: $noFocus)

                TextField("Road Name", text: $roadName)
                    .focused($focusRoadNameField)
                
                HStack {
                    Button("Cancel", action: {
                        sheetOpen = false
                    }).keyboardShortcut(.cancelAction)
                    .padding()

                    Spacer()

                    Button("Add Road", action: {
                        print("=> Add road '\(roadName)'")
                        sheetOpen = false
                    }).keyboardShortcut(.defaultAction)
                    .padding()
                }
            }
            .frame(width: 260)
            .padding()
        })
        .frame(width: 100, height: 50)
    }
}

#Preview {
    ContentView()
}

Update: Thanks to Sweeper for the comment. I forgot that I am using Full Keyboard Access, so widgets like the Picker get keyboard focus with a focus ring. I've adjusted the example to use two text fields to show the buggy behavior even on systems which don't have Full Keyboard Access enabled, which is the default state.

Now, you will see the sheet always open with the first, "No focus" field selected, despite the second field having the .focused() modifier.

Share Improve this question edited Feb 7 at 12:23 Nick K9 asked Feb 6 at 14:02 Nick K9Nick K9 4,6631 gold badge36 silver badges80 bronze badges 2
  • 1 I cannot reproduce on macOS 15.1.1. The text field is focused as expected. – Sweeper Commented Feb 6 at 15:05
  • Thanks for your comment. I have adjusted the MRE to better illustrate the issue. I'm on macOS 15.2 with Xcode 16.2. – Nick K9 Commented Feb 7 at 12:24
Add a comment  | 

1 Answer 1

Reset to default 0

Sheets are modal, and I found that passing @FocusState can be tricky in iOS18+.

You could try this simple approach using two local @FocusState and a basic @State private var focus: Field? to pass the focus info to the sheet view. Note capturing the vars for use in the sheet, and the .onAppear.

Example code:

enum Field {
    case noFocus
    case roadName
}

struct ContentView: View {
    @State private var sheetOpen: Bool = false
    @State private var roadName: String = "some road"
    @State private var noFocus: String = "something"
    @State private var text: String = "test"
    
    @State private var focus: Field? // <--- to pass to sheet
    @FocusState private var focusField: Field?  // <--- local to this view

    
    var body: some View {
        VStack {
            Button("focus on roadName"){
                focus = .roadName // <--- here
                sheetOpen = true
            }
            Button("focus on noFocus"){
                focus = .noFocus // <--- here
                sheetOpen = true
            }
            .sheet(isPresented: $sheetOpen) { [$roadName, $noFocus, focus] in  // <--- here
                MidView(sheetOpen: $sheetOpen,
                        roadName: $roadName,
                        noFocus: $noFocus,
                        focus: focus)
            }
        }
    }
}

struct MidView: View {
    @Binding var sheetOpen: Bool
    @Binding var roadName: String
    @Binding var noFocus: String

    var focus: Field?  // <--- here
    @FocusState private var focusField: Field? // <--- local to this view

    
    var body: some View {
        VStack {
            TextField("No focus", text: $noFocus)
                .focused($focusField, equals: .noFocus)

            TextField("Road Name", text: $roadName)
                .focused($focusField, equals: .roadName)
            
            HStack {
                Button("Cancel", action: {
                    sheetOpen = false
                }).keyboardShortcut(.cancelAction)
                .padding()

                Spacer()

                Button("Add Road", action: {
                    print("----> Add road '\(roadName)'")
                    sheetOpen = false
                }).keyboardShortcut(.defaultAction)
                .padding()
            }
        }
        .frame(width: 260)
        .padding()
        .onAppear {
            focusField = focus  // <--- here
        }
    }
}
发布评论

评论列表(0)

  1. 暂无评论