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

使用Supabase完成iOS注册后无法跳转至后续视图的排查求助

问题:注册成功后无法跳转至PersonalizationView

使用Supabase开发iOS应用时,点击注册按钮后,数据库中能成功创建用户,但应用不会跳转到后续的PersonalizationView,无任何操作反馈,控制台也没有输出预期的调试信息。

相关代码

SignUpView.swift

import SwiftUI
import Supabase

struct SignUpView: View {
    @StateObject private var viewModel = SignUpViewModel()
    @State private var activeNavigation: SignUpNavigation?
    @State private var email: String = ""
    @State private var password: String = ""
    @State private var confirmPassword: String = ""
    @State private var errorMessage: String = ""
    @Binding var isSignUpViewVisible: Bool
    @Environment(\.presentationMode) var presentationMode
    
    var body: some View {
            VStack {
                Text("Sign Up")
                    .font(.largeTitle)
                    .fontWeight(.bold)
                    .padding(.bottom, 20)
                
                TextField("Email", text: $email)
                    .padding()
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .autocapitalization(.none)
                    .disableAutocorrection(true)
                
                SecureField("Password", text: $password)
                    .padding()
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                
                SecureField("Confirm Password", text: $confirmPassword)
                    .padding()
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                
                if !errorMessage.isEmpty {
                    Text(errorMessage)
                        .foregroundColor(.red)
                        .padding()
                }
                
                Button(action: signUp) {
                    Text("Sign Up")
                        .font(.title2)
                        .fontWeight(.bold)
                        .padding()
                        .frame(maxWidth: .infinity)
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(10)
                        .padding(.horizontal, 40)
                        .padding(.top, 20)
                }
                
                Spacer()
                
                Button(action: {
                    presentationMode.wrappedValue.dismiss()
                }) {
                    Text("Already have an account? Log In")
                        .font(.footnote)
                        .foregroundColor(.blue)
                        .padding(.bottom, 10)
                }
                
                NavigationLink(value: activeNavigation, label: {
                    switch activeNavigation {
                    case .personalization:
                        PersonalizationView()
                    case .interviewAI:
                        InterviewAIView()
                    case .none:
                        EmptyView()
                    }
                })
                .opacity(0) // Hide the NavigationLink
            }
            .padding(.top, 60)
            .padding(.horizontal, 20)
        }
    
    
    
    private func signUp() {
        // Password validation before signUp
        if password != confirmPassword {
            errorMessage = "Passwords do not match."
            return
        }
        
        viewModel.signUp(email: email, password: password) { error in
            if let error = error {
                errorMessage = "Sign Up Error: \(error.localizedDescription)"
                print("Error during sign up: \(error.localizedDescription)") // Debug print
            } else {
                print("Sign up successful") // Debug print
                self.activeNavigation = .personalization
                print("Navigating to PersonalizationView") // Debug print
            }
        }
    }
}

enum SignUpNavigation: Identifiable {
    case personalization
    case interviewAI
    
    var id: Self { self }
}

struct SignUpView_Previews: PreviewProvider {
    static var previews: some View {
        SignUpView(isSignUpViewVisible: .constant(true))
    }
}

SignUpViewModel.swift

import Foundation
import SwiftUI
import Supabase

class SignUpViewModel: ObservableObject {
    let supabaseURLString = "Bob Seger"
    let supabaseKeyString = "Bob Seger"
    let client: SupabaseClient

    init() {
        client = SupabaseClient(supabaseURL: URL(string: supabaseURLString)!, supabaseKey: supabaseKeyString)
    }

    func signUp(email: String, password: String, completion: @escaping (Error?) -> Void) {
        Task {
            do {
                try await client.auth.signUp(email: email, password: password)
                completion(nil)
            } catch {
                completion(error)
            }
        }
    }
}
排查与解决建议
  • 强制主线程更新状态:ViewModel的signUp方法在后台Task中执行,completion闭包默认运行在后台线程,而SwiftUI状态更新必须在主线程。修改ViewModel的代码,将completion调用切换到主线程:
    func signUp(email: String, password: String, completion: @escaping (Error?) -> Void) {
        Task {
            do {
                try await client.auth.signUp(email: email, password: password)
                DispatchQueue.main.async {
                    completion(nil)
                }
            } catch {
                DispatchQueue.main.async {
                    completion(error)
                }
            }
        }
    }
    
  • 确认导航容器层级:当前使用的NavigationLink(value:)需要依赖父视图的NavigationStack(iOS16+)或NavigationView(iOS15及以下),检查父视图是否正确包裹了导航容器,否则跳转不会生效。
  • 完善调试打印:在ViewModel的Task中添加打印语句,确认请求流程是否执行到completion:
    Task {
        print("开始注册请求")
        do {
            try await client.auth.signUp(email: email, password: password)
            print("注册请求成功")
            DispatchQueue.main.async {
                completion(nil)
            }
        } catch {
            print("注册请求失败:\(error)")
            DispatchQueue.main.async {
                completion(error)
            }
        }
    }
    
  • 替换导航链接实现方式:用opacity(0)隐藏导航链接的方式容易出问题,建议改用iOS16+的navigationDestination:
    var body: some View {
        VStack {
            // 原有视图内容
        }
        .navigationDestination(for: SignUpNavigation.self) { destination in
            switch destination {
            case .personalization:
                PersonalizationView()
            case .interviewAI:
                InterviewAIView()
            }
        }
    }
    
    之后只需设置activeNavigation = .personalization即可触发跳转,无需隐藏的NavigationLink。
  • 验证目标视图可用性:先将PersonalizationView替换为简单测试视图,确认跳转逻辑本身没问题:
    struct PersonalizationView: View {
        var body: some View {
            Text("Personalization 测试视图")
                .font(.largeTitle)
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:55:42