macOS SwiftUI Sheet中TextField无法按预期获取焦点问题
macOS SwiftUI Sheet中默认聚焦第二个TextField的问题解决方法
在macOS平台使用SwiftUI开发时,若Sheet内包含两个TextField,尝试通过@FocusState变量控制让第二个TextField在Sheet打开时获得焦点,但即使将绑定变量设为true,始终是第一个TextField获焦,即使在默认未开启全键盘访问的系统设置下该问题依然存在。
问题原因
直接在打开Sheet的按钮动作中设置focusRoadNameField = true时,Sheet的视图尚未完成渲染,此时的焦点设置会被系统默认的焦点逻辑(自动聚焦第一个可交互控件)覆盖,导致设置不生效。
解决方案
在Sheet的内容视图完成渲染后,再触发焦点设置。可以通过onAppear修饰符结合异步调度,确保TextField已完成初始化后再设置焦点。
修改后的完整代码
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 = "" }) { 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() .onAppear { // 异步调度确保视图完全渲染后设置焦点 DispatchQueue.main.async { focusRoadNameField = true } } }) .frame(width: 100, height: 50) } } #Preview { ContentView() }
说明
- 移除了按钮动作中直接设置
focusRoadNameField = true的代码,转而在Sheet视图的onAppear回调中异步设置焦点。 - 使用
DispatchQueue.main.async可以确保TextField已完成视图挂载,此时设置焦点不会被系统默认逻辑覆盖。
内容的提问来源于stack exchange,提问作者Nick K9
相关产品推荐
相关产品推荐

