首页 > 解决方案 > 从 SwiftUI 视图调用本地 UIViewController 函数

问题描述

我正在尝试从 ContentView 调用本地 ViewController 函数。该函数使用一些局部变量,不能移到 ViewController 之外。

class ViewController: UIViewController {
    func doSomething() {...}
} 

extension ViewController : LinkViewDelegate {...}

位于不同的文件中:

struct ContentView: View {

    init() {
        viewController = .init(nibName:nil, bundle:nil)
    }
    var viewController: viewController

var body: some View {
    Button(action: {self.viewController.doSomething()}) {
            Text("Link Account")
        }
    }
}

UIViewController 不能更改为 UIViewRepresentable 之类的东西,因为 LinkViewDelegate 只能扩展 UIViewController。

标签: iosswiftviewswiftui

解决方案


这是我想出的一种方法,它不会导致“在视图更新期间修改状态,这将导致未定义的行为”问题。诀窍是将您的 ViewModel 的引用传递给 ViewController 本身,然后重置调用您的函数的布尔值,而不是在您的 UIViewControllerRepresentable 中。

public class MyViewModel: ObservableObject {
    @Published public var doSomething: Bool = false
}


struct ContentView: View {

    @StateObject var viewModel = MyViewModel()

    var body: some View {
        MyView(viewModel: viewModel)

        Button("Do Something") {
            viewModel.doSomething = true
        }
    }
}


struct MyView: UIViewControllerRepresentable {
    
    @ObservedObject var viewModel: MyViewModel
    
    func makeUIViewController(context: Context) -> MyViewController {
        return MyViewController(viewModel)
    }
    
    func updateUIViewController(_ viewController: MyViewController, context: Context) {
        if viewModel.doSomething {
            viewController.doSomething()
            // boolean will be reset in viewController
        }
    }
}


class MyViewController: UIViewController {
    
    var viewModel: MyViewModel
    
    public init(_ viewModel: MyViewModel) {
        self.viewModel = viewModel
    }
    
    public func doSomething() {
        // do something, then reset the flag
        viewModel.doSomething = false
    }
}


推荐阅读