You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:53:14