SwiftUI注销完成后如何自动跳转至Register根视图?
解决SwiftUI注销后视图不自动刷新的问题
你的核心问题是ContentView没有监听UserDefaults的变化,直接在body里读取UserDefaults不会触发视图刷新。下面提供两种实用方案:
方案一:使用@AppStorage快速实现(适合简单场景)
@AppStorage是SwiftUI提供的直接绑定UserDefaults的属性包装器,会自动监听值的变化并刷新视图。
修改ContentView
struct ContentView: View { // 绑定UserDefaults中的"sessionKey",自动同步状态 @AppStorage("sessionKey") private var sessionKey: String? var body: some View { if let key = sessionKey { MainPage() } else { Register() } } }
修改LogOutView
注销成功后直接设置sessionKey为nil,@AppStorage会自动同步到UserDefaults并触发ContentView刷新:
struct LogOutView: View { @StateObject var loginModel = LoginViewModel() @AppStorage("sessionKey") private var sessionKey: String? var body: some View { VStack { Button(action: { print("Log Out Tapped...") guard let key = sessionKey else { return } loginModel.logOut(key: key) { success in if success { sessionKey = nil // 自动同步到UserDefaults,触发视图切换 } } }, label: { Text("Log Out") }) } } }
方案二:使用共享ViewModel(适合复杂登录状态管理)
如果你的APP有更多登录相关逻辑(比如用户信息、token校验等),推荐把登录状态统一放到ViewModel中,用@Published实现响应式刷新。
优化LoginViewModel
把sessionKey作为@Published属性,自动同步UserDefaults:
class LoginViewModel: ObservableObject { @Published var sessionKey: String? { didSet { // 自动同步到UserDefaults if let key = sessionKey { UserDefaults.standard.set(key, forKey: "sessionKey") } else { UserDefaults.standard.removeObject(forKey: "sessionKey") } } } // 初始化时从UserDefaults读取状态 init() { sessionKey = UserDefaults.standard.string(forKey: "sessionKey") } func logOut(key: String, completion: @escaping (Bool) -> Void) { // 原有的API注销逻辑 // 调用成功后直接更新sessionKey completion(true) sessionKey = nil } }
修改ContentView
使用@StateObject创建共享的ViewModel,并通过environmentObject传递给子视图:
struct ContentView: View { @StateObject private var loginModel = LoginViewModel() var body: some View { if let key = loginModel.sessionKey { MainPage() .environmentObject(loginModel) } else { Register() .environmentObject(loginModel) } } }
修改LogOutView
通过@EnvironmentObject获取共享的ViewModel,无需重复创建:
struct LogOutView: View { @EnvironmentObject var loginModel: LoginViewModel var body: some View { VStack { Button(action: { print("Log Out Tapped...") guard let key = loginModel.sessionKey else { return } loginModel.logOut(key: key) { success in // 无需手动操作UserDefaults,ViewModel已自动处理 } }, label: { Text("Log Out") }) } } }
为什么原有代码不生效?
SwiftUI的视图刷新只依赖响应式状态(比如@State、@Binding、@Published、@AppStorage等),直接在body中读取UserDefaults属于一次性读取,不会监听后续变化,所以注销后ContentView不会自动刷新。
内容的提问来源于stack exchange,提问作者Schwifty
相关产品推荐
相关产品推荐

