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 次 |
最近记录: |