【问题标题】:Call a function from SwiftUI in UIHostingController在 UIHostingController 中从 SwiftUI 调用函数
【发布时间】:2020-04-01 07:35:14
【问题描述】:

我有一个 swift UIHostingController 可以呈现 SwiftUI。我调用了一个视图中的函数,该函数构建得很好,但没有创建预期的输出。

class LoginView: UIHostingController<LoginViewComponent> {
    required init?(coder: NSCoder) {
        super.init(coder: coder, rootView: LoginViewComponent())
    }

    override func viewDidAppear(_ animated: Bool) {
        sessionHandler()
    }

    func sessionHandler(){
        let user = User()
        if user.isLoggedIn(){
            view.isUserInteractionEnabled = false
            print("Authenticating Session")
            self.rootView.loginState(state: "success")
        }else{
            view.isUserInteractionEnabled = true
            print("Needs Logging in")
        }
    }

}

函数 ("loginState(state: "success")") 在 SwiftUI 视图类中调用时有效,但是从宿主控制器调用时它不起作用。

任何帮助将不胜感激。

【问题讨论】:

  • 为什么不能在 LoginViewComponent 中完成所有这些操作?正如@Asperi 提到的,您可以使用模型对象来跟踪用户状态,然后在整个视图上使用 SwiftUI 的 .disabled(_:) 修饰符。 disabled 参数的值将来自您的状态对象。

标签: ios swift xcode swiftui swift5


【解决方案1】:

SwiftUI 实际上是反应式状态机,所有视图都是结构值,所以你需要改变概念,而不是强制发送消息指定状态依赖和对这些状态的反应......

因此,保留您的自定义主机控制器,它可以设置如下

import SwiftUI
import UIKit
import Combine

// model that keeps login state
class LoginState: ObservableObject {
    @Published var state: String = ""
}

struct LoginViewComponent: View {
    @EnvironmentObject var loginState: LoginState // state to be observed

    ...
   // somewhere in body you use loginState.state
   // and view will be refreshed depending on state changes
}

class LoginView: UIHostingController<AnyView> {
    let loginState = LoginState() // here it is created

    required init?(coder: NSCoder) {
        super.init(coder: coder, rootView: AnyView(LoginViewComponent().environmentObject(self.loginState))) // here the ref injected
    }

    override func viewDidAppear(_ animated: Bool) {
        sessionHandler()
    }

    func sessionHandler(){
        let user = User()
        if user.isLoggedIn(){
            view.isUserInteractionEnabled = false
            print("Authenticating Session")
            self.loginState.state = "success" // here state changed
        }else{
            view.isUserInteractionEnabled = true
            print("Needs Logging in")
        }
    }

}

【讨论】:

  • 您好,感谢您的回复,当尝试将环境对象设置为 loginview 组件时,我收到以下错误:“无法将 'some View' 类型的值转换为预期的参数类型 'LoginViewComponent '"
  • 是的,你是对的......看起来在这种情况下需要类型擦除......不是很优雅。继承不适用于 SwiftUI。
猜你喜欢
  • 2021-07-23
  • 2022-11-05
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 2023-03-12
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多