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

SwiftUI实现UserProfiling未完成时禁止跳转ContentView的问题

问题描述

需求逻辑:

  • 用户首次登录或未完成UserProfiling时,禁止跳转到ContentView
  • 用户已完成UserProfiling时,自动跳转至ContentView

当前问题:完成UserProfiling后无法自动跳转,必须重启应用才能进入ContentView


相关代码

UserProfiling ViewModel

class UserProfiling: ObservableObject {
    @Published var selectedLanguages: [String] = []
    @Published var isProfileCompleted: Bool =  false
    private var db = Firestore.firestore()
    private var userId: String?
    
    init()  {
            if let userId = Auth.auth().currentUser?.uid {
                self.userId = userId
                checkUserProfiling()
            }
        }
    
    func checkUserProfiling() -> Bool {
        guard let userId = Auth.auth().currentUser?.uid else {
            return false
        }
        
        db.collection("users").document(userId).getDocument { snapshot, error in
            if let error = error {
                print("Error getting user profiling: \(error.localizedDescription)")
            } else if let snapshot = snapshot, snapshot.exists {
                let data = snapshot.data()
                if let isProfileCompleted = data?["isProfileCompleted"] as? Bool {
                        self.isProfileCompleted = isProfileCompleted
                }
            }
        }
        return isProfileCompleted
    }
    
    
    func saveUserProfiling(completion: @escaping (Bool) -> Void) {
        print(selectedLanguages)
        guard let uid = Auth.auth().currentUser?.uid else {
            completion(false)
            return
        }
        
        let documentRef = db.collection("users").document(uid)
        
        documentRef.setData([
            "selectedLanguages": selectedLanguages,
            "isProfileCompleted": true
        ], merge: true) { error in
            if let error = error {
                print("Error saving user profiling data to firestore :\(error.localizedDescription)")
                completion(false)
            } else {
                print("User profiling data saved to firestore successfully.")
                DispatchQueue.main.async {
                    self.isProfileCompleted = true
                }
                completion(true)
            }
        }
    }
}

MoovieApp.swift

//
//  MoovieApp.swift
//  Moovie
//
//  Created by Putut Yusri Bahtiar on 26/03/23.
//

import SwiftUI
import FirebaseCore

@main
struct MoovieApp: App {
    @StateObject var sessionAuth = SessionAuth()
    @StateObject var userProfiling = UserProfiling()
    
    init() {
        FirebaseApp.configure()
    }
    
    var body: some Scene {
        WindowGroup {
            if sessionAuth.isLoggedIn {
                if userProfiling.isProfileCompleted {
                    ContentView()
                        .environmentObject(sessionAuth)
                        .environmentObject(userProfiling)
                } else {
                    UserProfilingView()
                        .environmentObject(sessionAuth)
                        .environmentObject(userProfiling)
                }
            } else {
                LoginView()
                    .environmentObject(sessionAuth)
            }
        }
    }
}

问题分析与修复方案

核心问题

  1. checkUserProfiling异步逻辑错误:该方法返回值时,Firestore的异步请求还未完成,返回的是初始默认值false。后续异步回调更新isProfileCompleted时,初始视图已经渲染完成,不会自动刷新。
  2. 登录状态变更未触发Profile检查:UserProfiling的checkUserProfiling仅在初始化时调用一次,若用户是在App启动后登录(从LoginView跳转),不会重新检查Profile状态。

修复步骤

1. 修正checkUserProfiling方法

去掉无效的返回值,专注于异步更新isProfileCompleted:

func checkUserProfiling() {
    guard let userId = Auth.auth().currentUser?.uid else {
        self.isProfileCompleted = false
        return
    }
    
    db.collection("users").document(userId).getDocument { snapshot, error in
        if let error = error {
            print("Error getting user profiling: \(error.localizedDescription)")
            self.isProfileCompleted = false
        } else if let snapshot = snapshot, snapshot.exists {
            let data = snapshot.data()
            self.isProfileCompleted = data?["isProfileCompleted"] as? Bool ?? false
        } else {
            self.isProfileCompleted = false
        }
    }
}

2. 监听登录状态,触发Profile检查

在MoovieApp中,当sessionAuth.isLoggedIn变为true时,重新调用checkUserProfiling:

@main
struct MoovieApp: App {
    @StateObject var sessionAuth = SessionAuth()
    @StateObject var userProfiling = UserProfiling()
    
    init() {
        FirebaseApp.configure()
    }
    
    var body: some Scene {
        WindowGroup {
            if sessionAuth.isLoggedIn {
                // 登录状态变更时重新检查Profile
                let _ = sessionAuth.$isLoggedIn
                    .sink { isLoggedIn in
                        if isLoggedIn {
                            userProfiling.checkUserProfiling()
                        }
                    }
                
                if userProfiling.isProfileCompleted {
                    ContentView()
                        .environmentObject(sessionAuth)
                        .environmentObject(userProfiling)
                } else {
                    UserProfilingView()
                        .environmentObject(sessionAuth)
                        .environmentObject(userProfiling)
                }
            } else {
                LoginView()
                    .environmentObject(sessionAuth)
            }
        }
    }
}

3. 保留现有saveUserProfiling逻辑

saveUserProfiling中已经在主线程更新isProfileCompleted,这部分是正确的,@Published属性变更会自动触发视图刷新,完成Profile后无需额外操作即可跳转。


内容的提问来源于stack exchange,提问作者Putyourz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:17:01