You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:03:16