SwiftUI中如何在结构体外部的Handler中访问视图的State变量?
解决思路与实现方案
你的思路方向是对的,但原代码里的Action.handler是无参闭包,外部无法直接访问ActionView内部的@State变量output。下面提供几种可行的实现方式:
方式一:让Handler接受Binding参数
修改Action结构体的handler定义,让它接受Binding<String>类型的参数,这样在ActionView内部调用handler时,把$output传递进去,外部就能通过绑定修改文本内容。
struct ActionView: View { struct Action { // 修改handler为接受Binding<String>的闭包 let handler: (Binding<String>) -> () } @State var output: String = "a\nb\nc" let action: Action var body: some View { List { Button(action: { // 调用handler时传入output的绑定 action.handler($output) }) { Label("Action", systemImage: "play") } TextEditor(text: $output) } } } struct ActionView_Previews: PreviewProvider { static var previews: some View { let action = ActionView.Action(handler: { outputBinding in // 执行操作后,通过绑定修改output let newContent = "执行操作后的新内容\n新增一行文本" outputBinding.wrappedValue = newContent }) ActionView(action: action) } }
方式二:让Handler返回要设置的字符串
如果handler的逻辑只是生成新的文本内容,可以让闭包返回String,ActionView内部直接将返回值赋值给output:
struct ActionView: View { struct Action { let handler: () -> String } @State var output: String = "a\nb\nc" let action: Action var body: some View { List { Button(action: { // 将handler返回的内容赋值给output output = action.handler() }) { Label("Action", systemImage: "play") } TextEditor(text: $output) } } } struct ActionView_Previews: PreviewProvider { static var previews: some View { let action = ActionView.Action(handler: { // 执行操作,返回新内容 return "处理完成:\n当前时间:\(Date())" }) ActionView(action: action) } }
方式三:使用ObservableObject管理状态
如果业务逻辑更复杂,推荐将状态抽离到ViewModel中,外部handler持有ViewModel的引用直接修改:
class ActionViewModel: ObservableObject { @Published var output: String = "a\nb\nc" } struct ActionView: View { struct Action { let handler: (ActionViewModel) -> () } @StateObject var viewModel = ActionViewModel() let action: Action var body: some View { List { Button(action: { action.handler(viewModel) }) { Label("Action", systemImage: "play") } TextEditor(text: $viewModel.output) } } } struct ActionView_Previews: PreviewProvider { static var previews: some View { let action = ActionView.Action(handler: { viewModel in // 直接修改ViewModel的output viewModel.output = "通过ViewModel更新的内容\n支持复杂逻辑处理" }) ActionView(action: action) } }
这几种方式都能实现「执行操作后修改TextEditor内容」的需求,你可以根据实际业务复杂度选择合适的方案。
内容的提问来源于stack exchange,提问作者Manuel
相关产品推荐
相关产品推荐

