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

SwiftUI问题:非根视图中TextField的键盘工具栏不显示

iOS 18.2设备上NavigationStack推送子视图后TextField键盘工具栏不显示问题

问题现象

  • 在运行iOS 18.2的iPhone 12 Pro设备上,根视图使用NavigationStack,推送包含TextField的子视图后,TextField获得焦点时,带Done按钮的键盘工具栏无法显示。
  • 将该TextField直接放在根视图中,键盘工具栏可正常显示。
  • iOS 18模拟器无此异常。

代码重现

struct HomeView: View
{
    @State private var navigationDestinationIsPresented = false
    
    var body: some View
    {
        NavigationStack
        {
            Button("Push Me")
            {
                self.navigationDestinationIsPresented = true
            }
            .buttonStyle(.borderedProminent)
            .navigationDestination(isPresented: self.$navigationDestinationIsPresented)
            {
                NextView()
            }
        }
    }
}

struct NextView: View
{        
    var body: some View
    {
        NumTextField()
    }
 }

struct NumTextField: View
{
    @State private var userInput: String = ""
    @FocusState var isFocused: Bool
    
    var body: some View
    {
        TextField("", text: self.$userInput)
        .border(Color.black, width: 1.0)
        .frame(width: 45)
        .multilineTextAlignment(.center)
        #if os(iOS)
        .keyboardType(.numberPad)
        .toolbar
        {
            if (self.isFocused)
            {
                ToolbarItemGroup(placement: .keyboard)
                {
                    Spacer()
                    
                    Button("Done")
                    {
                        self.isFocused = false
                    }
                }
            }
        }
        #endif
        .focused(self.$isFocused)
    }
}

解决方案

方案1:用toolbar(_:for:)控制显隐,避免条件渲染Toolbar内容

iOS 18.2中,推送子视图的层级下,基于FocusState的条件渲染可能导致Toolbar无法被导航上下文正确识别。改为始终声明Toolbar内容,用toolbar(_:for:)控制键盘工具栏的显隐:

struct NumTextField: View
{
    @State private var userInput: String = ""
    @FocusState var isFocused: Bool
    
    var body: some View
    {
        TextField("", text: $userInput)
            .border(Color.black, width: 1.0)
            .frame(width: 45)
            .multilineTextAlignment(.center)
            #if os(iOS)
            .keyboardType(.numberPad)
            // 始终声明Toolbar内容
            .toolbar {
                ToolbarItemGroup(placement: .keyboard) {
                    Spacer()
                    Button("Done") {
                        isFocused = false
                    }
                }
            }
            // 根据焦点状态控制键盘工具栏的显隐
            .toolbar(isFocused ? .visible : .hidden, for: .keyboard)
            #endif
            .focused($isFocused)
    }
}

方案2:将Toolbar提升到子视图根层级

把Toolbar附加到推送的子视图(NextView)上,而非TextField的修饰符中,确保导航上下文能正确识别Toolbar:

struct NextView: View
{
    @FocusState private var isFocused: Bool
    
    var body: some View
    {
        NumTextField(isFocused: $isFocused)
            .toolbar {
                ToolbarItemGroup(placement: .keyboard) {
                    Spacer()
                    Button("Done") {
                        isFocused = false
                    }
                }
            }
    }
}

struct NumTextField: View
{
    @State private var userInput: String = ""
    @Binding var isFocused: Bool
    
    var body: some View
    {
        TextField("", text: $userInput)
            .border(Color.black, width: 1.0)
            .frame(width: 45)
            .multilineTextAlignment(.center)
            #if os(iOS)
            .keyboardType(.numberPad)
            #endif
            .focused($isFocused)
    }
}

原因分析

该问题大概率是iOS 18.2中NavigationStack推送子视图时,焦点状态更新与Toolbar视图渲染的同步bug。原代码仅在isFocused为true时渲染Toolbar,导致视图层级变化时导航上下文未及时注册Toolbar;模拟器因环境差异未触发该bug。

内容的提问来源于stack exchange,提问作者Ser Pounce

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:27:36