SwiftUI应用强制重启后UsernameView短暂闪现问题求助
SwiftUI重启App后UsernameView短暂显示问题修复
问题根源
RootViewModel里的hasUsername初始值是false,App启动时,异步获取用户名的请求还没完成,视图会先触发!viewModel.hasUsername分支显示UsernameView。等异步请求结束,hasUsername更新为true,视图立刻切到TabbarView,就出现了短暂闪屏的情况。
解决方案1:添加加载状态过渡
给ViewModel加个加载标记,在获取用户信息完成前显示加载视图,避免提前跳转到UsernameView。
修改RootViewModel:
@MainActor final class RootViewModel: ObservableObject { @Published private(set) var userUsername: [UserUsername] = [] @Published var hasUsername: Bool = false @Published var isLoading: Bool = true // 新增加载状态 func getUsername() async throws { defer { isLoading = false } // 请求结束后关闭加载 let authDataresult = try AuthenticationManager.shared.getAuthenticatedUser() self.userUsername = try await UserManager.shared.getUsername(userId: authDataresult.uid) hasUsername = self.userUsername.count >= 1 } }
修改RootView的视图逻辑:
struct RootView: View { @StateObject private var viewModel = RootViewModel() @State private var showSignInView: Bool = false var body: some View { ZStack { if showSignInView { NavigationStack { AuthenticationView(showSignInView: $showSignInView) } } else if viewModel.isLoading { // 这里可以换成自定义加载页,比如带logo的ProgressView ProgressView("加载中...") } else if !viewModel.hasUsername { UsernameView(hasUsername: $viewModel.hasUsername) } else { TabbarView(showSignInView: $showSignInView) } } .onAppear { let authUser = try? AuthenticationManager.shared.getAuthenticatedUser() self.showSignInView = authUser == nil ? true : false Task { if let authenticatedUser = authUser { print("User signed in with uid: \(authenticatedUser.uid)") try? await viewModel.getUsername() print(viewModel.userUsername.count) } else { print("No user signed in!") viewModel.isLoading = false // 未登录时直接结束加载 } } } } }
解决方案2:优先读取本地缓存
如果你的UserManager支持本地缓存,可以在ViewModel初始化时先读取缓存的用户名状态,跳过异步请求的等待时间:
@MainActor final class RootViewModel: ObservableObject { @Published private(set) var userUsername: [UserUsername] = [] @Published var hasUsername: Bool = false init() { // 初始化时先读本地缓存 if let cachedUsername = UserManager.shared.getCachedUsername() { userUsername = [cachedUsername] hasUsername = true } } func getUsername() async throws { let authDataresult = try AuthenticationManager.shared.getAuthenticatedUser() self.userUsername = try await UserManager.shared.getUsername(userId: authDataresult.uid) hasUsername = self.userUsername.count >= 1 // 更新本地缓存 UserManager.shared.cacheUsername(userUsername.first) } }
这样App启动时直接用缓存状态,不会进入UsernameView分支,同时异步请求会同步最新数据,彻底避免闪屏。
内容的提问来源于stack exchange,提问作者Ali Almahoozi
相关产品推荐
相关产品推荐

