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

SwiftUI添加Sheet修饰符后FocusedField始终为空问题求助

问题解决:Sheet内TextField的FocusState无法更新

核心原因

  1. 使用.constant(true)控制Sheet显示,会导致SwiftUI频繁重新初始化Sheet,重置焦点状态。
  2. Sheet作为独立模态视图,父视图的@FocusState与Sheet内TextField的绑定在不稳定的生命周期下无法正常同步。

解决方案

方案1:父视图感知焦点状态(推荐)

将Sheet内容抽为独立子视图,用@FocusState.Binding传递父视图的焦点状态,同时改用@State变量管理Sheet显示:

enum TripField: Hashable {
    case pickup, destination
}

struct Trip {
    var pickup = ""
    var destination = ""
}

struct PlanYourRideScreen: View {
    
    @FocusState private var focusedField: TripField?
    @State private var trip = Trip()
    @State private var showSheet = true // 用State控制Sheet显示
    
    var body: some View {
        VStack {
            Map {}
        }
        .task(id: trip) {
            print("task")
            print(focusedField) // 现在能正确输出焦点状态
        }
        .sheet(isPresented: $showSheet) {
            RideInputSheet(trip: $trip, focusedField: $focusedField)
        }
    }
}

// 独立Sheet子视图
struct RideInputSheet: View {
    @Binding var trip: Trip
    @FocusState.Binding var focusedField: TripField?
    
    var body: some View {
        VStack(spacing: 12) {
            RoundedRectangle(cornerRadius: 8)
                .stroke(Color.gray, lineWidth: 1)
                .frame(height: 50)
                .overlay(
                    HStack {
                        Image(systemName: "circle.fill")
                            .foregroundColor(.blue)
                        TextField("Pickup location", text: $trip.pickup)
                            .textFieldStyle(PlainTextFieldStyle())
                            .padding(.leading, 5)
                            .focused($focusedField, equals: .pickup)
                    }
                    .padding(.horizontal)
                )
            
            // 可选:添加目的地输入框
            RoundedRectangle(cornerRadius: 8)
                .stroke(Color.gray, lineWidth: 1)
                .frame(height: 50)
                .overlay(
                    HStack {
                        Image(systemName: "mappin.circle.fill")
                            .foregroundColor(.red)
                        TextField("Destination", text: $trip.destination)
                            .textFieldStyle(PlainTextFieldStyle())
                            .padding(.leading, 5)
                            .focused($focusedField, equals: .destination)
                    }
                    .padding(.horizontal)
                )
        }
        .padding()
    }
}

方案2:Sheet内部独立管理焦点

如果父视图不需要感知Sheet内的焦点状态,直接在子视图内部声明@FocusState,隔离状态管理:

struct RideInputSheet: View {
    @Binding var trip: Trip
    @FocusState private var focusedField: TripField? // 子视图内部管理焦点
    
    var body: some View {
        // 同上UI代码
    }
}

关键修改点

  • 替换.constant(true)为@State变量:让SwiftUI正确管理Sheet的生命周期,避免不必要的重渲染。
  • 抽离Sheet子视图:明确视图层级,确保状态绑定的稳定性。

内容的提问来源于stack exchange,提问作者john doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:28:17