Swiftui 如何让UIButton(UIViewControllerRepresentable)触发模型中的操作?

Swiftui 如何让UIButton(UIViewControllerRepresentable)触发模型中的操作?,swiftui,Swiftui,我想让ui视图控制器中的ui按钮在我的SwiftUI应用程序中的observeObject中运行函数。我的需求比这更大,所以我在代码中删减了一些内容: UIViewController和委托 protocol TestVCDelegate { func runTest() } class TestVC: UIViewController { let btnTest = UIButton() let lblTest = UILabel() var delegate:

我想让
ui视图控制器中的
ui按钮
在我的SwiftUI应用程序中的
observeObject
中运行函数。我的需求比这更大,所以我在代码中删减了一些内容:

UIViewController和委托

protocol TestVCDelegate {
    func runTest()
}
class TestVC: UIViewController {
    let btnTest = UIButton()
    let lblTest = UILabel()
    var delegate:TestVCDelegate! = nil

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.red

        btnTest.translatesAutoresizingMaskIntoConstraints = false
        lblTest.translatesAutoresizingMaskIntoConstraints = false

        btnTest.backgroundColor = UIColor.green
        btnTest.addTarget(self, action: #selector(runTest), for: .touchUpInside)
        view.addSubview(btnTest)
        btnTest.heightAnchor.constraint(equalToConstant: 100).isActive = true
        btnTest.widthAnchor.constraint(equalToConstant: 100).isActive = true
        btnTest.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
        btnTest.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 100).isActive = true

        view.addSubview(lblTest)
        lblTest.heightAnchor.constraint(equalToConstant: 100).isActive = true
        lblTest.widthAnchor.constraint(equalToConstant: 100).isActive = true
        lblTest.topAnchor.constraint(equalTo: btnTest.bottomAnchor, constant: 10).isActive = true
        lblTest.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 100).isActive = true
}

    @objc func runTest() {
        delegate.runTest()
        lblTest.text = "hello world!"
    }
}
UIViewControllerRepresentable&Coordinator

struct Take2: UIViewControllerRepresentable {
    @EnvironmentObject var model: Model
    let testVC = TestVC()
    func makeUIViewController(context: Context) -> TestVC {
        testVC.delegate = context.coordinator
        return testVC
    }
    func updateUIViewController(_ uiViewController: TestVC, context: Context) {
        //
    }
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    class Coordinator: NSObject, TestVCDelegate {
        var parent: Take2
        init(_ testViewController: Take2) {
            parent = testViewController
        }
        func runTest() {
            print("hello world")
        }
    }
}
型号

class Model : ObservableObject {
    var objectWillChange = PassthroughSubject<Void, Never>()
    @Published var lblText = "" {
        willSet {
            objectWillChange.send()
        }
    }
    func runTest() {
        print("yet again, hello world")
        lblText = "hello world!"
    }
}
类模型:ObservableObject{
var objectWillChange=PassthroughSubject()
@已发布的变量lblText=“”{
意志{
objectWillChange.send()
}
}
func runTest(){
打印(“再一次,你好,世界”)
lblText=“你好,世界!”
}
}
每次我尝试在我的模型中执行
runTest()
,都会出现以下错误:

致命错误:读取EnvironmentObject outside View.body

现在,无论我是在
Take2
中,还是在
协调器中,还是在我的
TestVC
中,都会发生此错误。我(大部分)理解错误-如果我尝试通过
onAppear
some视图中执行此操作,它会工作。但是-我认为
UIViewControllerRepresentable
SwiftUI
堆栈的
视图(即使它不是
某些视图

我已经成功地将
UIKit
属性(get和set)公开到SwiftUI堆栈中。我还有
UIKit
代理(特别是
UIimagepickerController
)成功更新SwiftUI属性


但是如何从UIKit
UIButton
执行
ObservableObject
中的函数呢?

可能有背景说明为什么需要查看.body
。您是否尝试过间接寻址-包装器
视图
拥有环境对象并将其传递到
Take2
a
PassthroughSubject
?您可以将此发布服务器与
.onReceive(publisher)
一起在包装器中使用,并调用
@EnvironmentObject
上的方法,而
Take2
只发送到此发布服务器上的信号以发出函数调用。我知道这是一个解决办法,但任何其他方法可能都更复杂。或者您可以使用
@已发布的
setter,因为setter变量是允许的可以调用更多的willSet/didSet。或者他们可以?相互测试。我一定会调查的。谢谢结果我很可能把我的问题弄错了。我(还)没有能够使用@Fabian的建议创建一个包装器
视图
——但到目前为止,我有了更好的方法-
通知
。(Doh!)我想看看我是否能够成功地应用来自
合并
(因此,mistag)的发布者-订阅者模式,我将在一天内为其他人在这里发布我的答案。可能需要
查看.body
的背景原因。您是否尝试过间接寻址-包装器
视图
拥有环境对象并将其传递到
Take2
a
PassthroughSubject
?您可以将此发布服务器与
.onReceive(publisher)
一起在包装器中使用,并调用
@EnvironmentObject
上的方法,而
Take2
只发送到此发布服务器上的信号以发出函数调用。我知道这是一个解决办法,但任何其他方法可能都更复杂。或者您可以使用
@已发布的
setter,因为setter变量是允许的可以调用更多的willSet/didSet。或者他们可以?相互测试。我一定会调查的。谢谢结果我很可能把我的问题弄错了。我(还)没有能够使用@Fabian的建议创建一个包装器
视图
——但到目前为止,我有了更好的方法-
通知
。(Doh!)我想看看我是否能成功地应用来自
Combine
(因此,mistag)的发布者-订阅者模式,我将在一天内为其他人在这里发布我的答案。