成功登录后,SwiftUI ObservedObject 未更新视图
Posted
技术标签:
【中文标题】成功登录后,SwiftUI ObservedObject 未更新视图【英文标题】:SwiftUI ObservedObject not updating view after successful login 【发布时间】:2020-08-05 16:22:01 【问题描述】:为了在成功登录后从我的根视图显示我的内容,我尝试使用ObservedObject
和EnvironmentObject
,但无济于事。
例如如下:
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
。还是不行。
我有两篇论文:
可能是视图没有正确设置Group
等。我也尝试使用@ViewBuilder
等,没有区别。
可能有两个LoginManager
实例,或者RootView
以某种方式重新初始化为isLoggedIn
为假的新实例。但我多年来一直在创建这样的 Swift 单例:
static let shared = LoginManager()
从来没有遇到过任何问题。
如cmets中所说,我在全部切换到@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
【问题讨论】:
顺便说一句,在使用断点进行一些调试之后,似乎以true
的条件重新创建了视图,然后立即用false
销毁并再次创建。
还有其他地方可以访问 LoginManager 吗?喜欢SegmentedView
使用它还是更改isLoggedIn
属性?
@mginn 否。有一个带有令牌的替代登录方案,但我现在正在测试用户名密码登录。我注意到我没有“关闭”通过导航链接从欢迎视图访问的登录视图。有时登录后视图不会重新创建或更新。
self.isLoggedIn = true
是否在主队列上执行?
@Mundi,不太确定要分享什么。这基本上就是你所拥有的。我在视图中添加了一个外部 VStack 以在视图模型上添加一个调用 login
的假“登录”按钮。我用DispatchQueue.main.asyncAfter
模拟了异步登录。就是这样
【参考方案1】:
我想我得到了错误。
我认为.sink(receiveCompletion:
总是有错误,因为我所指的模板。但是无论如何都会调用完成块。
不幸的是,如果你插入一个参数error in
,它永远不会是nil
,而是包含类似的东西
Combine.Subscribers.Completion<module.CustomError>.finished
所以我猜,你不应该再在那里检查错误。
【讨论】:
以上是关于成功登录后,SwiftUI ObservedObject 未更新视图的主要内容,如果未能解决你的问题,请参考以下文章
成功登录后 SwiftUI Firebase 身份验证关闭视图