0

为了在成功登录后从我的根视图显示我的内容,我尝试使用ObservedObjectEnvironmentObject,但无济于事。

例如如下:

struct RootView: View {

    @EnvironmentObject var loginManager: LoginManager

    var body: some View {
        Group {
            if loginManager.isLoggedIn {
                SegmentedView()
            }
            else {
                WelcomeView()
            }
        }
    }
}

class LoginManager: ObservableObject {
    
    static let shared = LoginManager()
    var cancellable = Set<AnyCancellable>()
    @Published var isLoggedIn = false

    ...
    
    func login(...) {
        ...
        // on success
        self.isLoggedIn = true
    }

LoginManager保留在环境中SceneDelegate并放入环境中:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    var loginManager = LoginManager.shared
    ...

    // the view passed to window.rootUiewController via UIHostingController
    let contentView = RootView().environmentObject(loginManager)

登录后,它会直接回到我的WelcomeView. 我错过了什么?

编辑

这是一个新的方面。我有一个视图模型LoginView来管理日期字段中的数据。当登录按钮被按下时,我login()在这个视图模型中调用一个方法。

我需要.sink在视图模型中进行两个回调,因为我必须通过将loading标志设置为 false 来关闭加载指示器。

所以我不能self.isLoggedIn = true直接调用,因为我在视图模型中,而不是LoginManager. 相反,我打电话

self.loginManager.isLoggedIn = true 

我怀疑这条线不起作用。

视图模型和登录管理器之间的连接是这样完成的

@ObservedObject var loginManager = LoginManager.shared

但是,在将其转移到 之后LoginManager,我确实是self.isLoggedIn从那里打电话的。它仍然无法正常工作。

我有两篇论文:

  1. 可能是视图没有正确设置Group等。我也尝试使用@ViewBuilder等,没有区别。

  2. 可能以某种方式存在两个实例LoginManager,或者以RootView某种方式重新初始化了一个新实例,其中isLoggedIn为假。但我多年来一直在创建这样的 Swift 单例:

    静态让共享 = LoginManager()

从来没有任何问题。

正如评论中提到的,我在全部切换到时遇到了另一个错误@EnvironmentObject

Fatal error: No ObservableObject of type LoginManager found. A View.environmentObject(_:) for LoginManager may be missing as an ancestor of this view.: file SwiftUI, line 0

4

1 回答 1

0

我想我得到了错误。

我假设.sink(receiveCompletion: 总是有一个错误,因为我指的是它的模板。但是无论如何都会调用完成块。

不幸的是,如果您插入一个参数error in,它将永远不会nil包含类似

Combine.Subscribers.Completion<module.CustomError>.finished

所以我想,你不应该再在那里检查错误。

于 2020-08-06T15:24:58.490 回答