Liv*_*Liv 6 view ios swift swiftui
我正在尝试从 ContentView 调用本地 ViewController 函数。该函数使用了一些局部变量,不能移动到 ViewController 之外。
class ViewController: UIViewController {
func doSomething() {...}
}
extension ViewController : LinkViewDelegate {...}
Run Code Online (Sandbox Code Playgroud)
位于不同的文件中:
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")
}
}
}
Run Code Online (Sandbox Code Playgroud)
UIViewController 不能更改为 UIViewRepresentable 之类的东西,因为 LinkViewDelegate 只能扩展 UIViewController。
因此,您需要在 SwiftUI 中创建一个简单的 bool 绑定,将其翻转为 true 以触发 UIKit viewController 中的函数调用,然后将其设置回 false,直到下次按下 swiftUI 按钮。(至于LinkViewDelegate防止类似的事情UIViewControllerRepresentable不应该阻止您,请使用 aCoordinator来处理委托调用。)
struct ContentView: View {
@State var willCallFunc = false
var body: some View {
ViewControllerView(isCallingFunc: $willCallFunc)
Button("buttonTitle") {
self.willCallFunc = true
}
}
}
struct ViewControllerView: UIViewControllerRepresentable {
@Binding var isCallingFunc: Bool
func makeUIViewController(context: Context) -> YourViewController {
makeViewController(context: context) //instantiate vc etc.
}
func updateUIViewController(_ uiViewController: YourViewController, context: Context) {
if isCallingFunc {
uiViewController.doSomething()
isCallingFunc = false
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我想出的一种方法,不会导致“在视图更新期间修改状态,这将导致未定义的行为”问题。技巧是将 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
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将 ViewController 的实例作为参数传递给 ContentView:
struct ContentView: View {
var viewController: ViewController // first v lowercase, second one Uppercase
var body: some View {
Button(action: { viewController.doSomething() }) { // Lowercase viewController
Text("Link Account")
}
}
init() {
self.viewController = .init(nibName:nil, bundle:nil) // Lowercase viewController
}
}
// Use it for the UIHostingController in SceneDelegate.swift
window.rootViewController = UIHostingController(rootView: ContentView()) // Uppercase ContentView
Run Code Online (Sandbox Code Playgroud)
更新了答案以更好地适合问题。
| 归档时间: |
|
| 查看次数: |
3473 次 |
| 最近记录: |