SwiftUI添加Sheet修饰符后FocusedField始终为空问题求助
问题解决:Sheet内TextField的FocusState无法更新
核心原因
- 使用
.constant(true)控制Sheet显示,会导致SwiftUI频繁重新初始化Sheet,重置焦点状态。 - 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
相关产品推荐
相关产品推荐

