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

SwiftUI中如何访问onSubmit修饰器传入的action参数?

问题

我基于UITextField实现了自定义的MyTextField(底层实现无需讨论),现有如下代码结构:

Form {
    MyTextField()
}
.onSubmit {
    // 需要触发的逻辑
}

SwiftUI的onSubmit修饰器定义如下:

extension View {
    public func onSubmit(of triggers: SubmitTriggers = .text, _ action: @escaping (() -> Void)) -> some View
}

当键盘的Return按钮按下时,我能收到UITextField的代理回调,希望在此回调中触发onSubmit传入的action。同时想了解:从更广泛的角度,如何访问View协议实现的视图修饰器所传入的任意参数?这些参数存储在何处?

解决方案

一、触发Form的onSubmit动作

SwiftUI中onSubmit(针对.text触发源)的提交动作是通过**环境(Environment)**传递的,你可以在MyTextField中读取对应的环境值,再在UITextField的代理回调中调用它,具体步骤如下:

  1. 在MyTextField中添加环境属性,读取文本提交动作:
struct MyTextField: UIViewRepresentable {
    // 读取系统文本类型的提交动作环境值
    @Environment(\.submitHandler) private var submitHandler
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.delegate = context.coordinator
        return textField
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        let parent: MyTextField
        
        init(_ parent: MyTextField) {
            self.parent = parent
        }
        
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            // 触发onSubmit传入的动作
            parent.submitHandler()
            textField.resignFirstResponder()
            return true
        }
    }
}
  1. 若需要兼容旧版本SwiftUI,可显式声明对应的环境键(系统内部已默认存在该键,此为示例):
private struct SubmitHandlerEnvironmentKey: EnvironmentKey {
    static let defaultValue: () -> Void = {}
}

extension EnvironmentValues {
    var submitHandler: () -> Void {
        get { self[SubmitHandlerEnvironmentKey.self] }
        set { self[SubmitHandlerEnvironmentKey.self] = newValue }
    }
}

完成上述修改后,当UITextField的Return按钮按下时,就能触发Form上onSubmit传入的action。

二、视图修饰器参数的存储与访问

视图修饰器的本质是返回一个包装后的View,传入的参数主要通过两种方式存储和传递:

  • 方式1:环境(Environment)传递
    像onSubmit、font、foregroundColor这类全局生效的系统修饰器,通常会把参数存入Environment。子视图可以通过@Environment属性直接读取对应的值,这是SwiftUI跨视图传递配置的标准方式。

  • 方式2:包装View的属性存储
    自定义修饰器一般会创建一个自定义View结构体,将传入的参数作为该结构体的属性存储。示例如下:

extension View {
    func customOverlay(text: String) -> some View {
        CustomOverlayView(content: self, overlayText: text)
    }
}

struct CustomOverlayView<Content: View>: View {
    let content: Content
    let overlayText: String // 修饰器参数存储在此处
    
    var body: some View {
        content
            .overlay(Text(overlayText))
    }
}

这种情况下,只有包装View能直接访问参数,如果子视图需要使用,需要通过环境或者显式传参的方式把参数向下传递。

总结

  • 系统修饰器的参数优先通过@Environment读取;
  • 自定义修饰器的参数,要么通过环境传递给子视图,要么在包装View中直接使用,若子视图需要则需显式传递。

内容的提问来源于stack exchange,提问作者Davyd Geyl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 12:51:35