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

iOS SwiftUI项目中@main入口触发Thread 1: EXC_BAD_ACCESS错误求助(点击注册按钮时触发)

Hey there, let's dig into this Thread 1: EXC_BAD_ACCESS error you're hitting when tapping the register button. I’ve spotted a critical issue that’s almost certainly causing this crash, plus a few other potential gotchas to fix up.


1. Critical Crash Cause: Duplicate AppDelegate Definitions

First off, your xxApp.swift file has three identical definitions of AppDelegate stacked on top of each other. This is a major problem—duplicate class definitions confuse the compiler and runtime, leading to invalid memory access (exactly the EXC_BAD_ACCESS error you’re seeing).

Fix: Clean Up Duplicate Code

Replace your entire xxApp.swift file with this corrected version (only one AppDelegate definition, plus fixed @main placement):

import SwiftUI
import Firebase

final class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        FirebaseApp.configure()
        return true
    }
}

@main
struct PSMAApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    @StateObject var sessionService = SessionServiceImpl()
    
    var body: some Scene {
        WindowGroup {
            NavigationView{
                switch sessionService.state {
                case .loggedIn:
                    HomeView()
                        .environmentObject(sessionService)
                case .loggedOut:
                    LoginView()
                }
            }
        }
    }
}

2. Potential Memory Leaks & Unmanaged Listeners

Even after fixing the duplicate class issue, there are two places where unmanaged listeners could cause future crashes or memory bloat:

Fix 1: Clean Up Firebase Auth & Database Listeners

Add a deinit method to your SessionServiceImpl to remove active listeners when the object is destroyed:

final class SessionServiceImpl: ObservableObject, SessionService {
    @Published var state: SessionState = .loggedOut
    @Published var userDetails: SessionUserDetails?
    private var handler: AuthStateDidChangeListenerHandle?
    private var databaseHandle: DatabaseHandle? // Add this
    
    init() {
        setupFirebaseAuthHandler()
    }
    
    func logout() {
        try? Auth.auth().signOut()
    }
    
    // Add this deinit method
    deinit {
        // Remove auth state listener
        if let authHandle = handler {
            Auth.auth().removeStateDidChangeListener(authHandle)
        }
        // Remove database value observer
        if let dbHandle = databaseHandle {
            Database.database().reference().child("users").removeObserver(withHandle: dbHandle)
        }
    }
}

private extension SessionServiceImpl {
    func setupFirebaseAuthHandler() {
        handler = Auth
            .auth()
            .addStateDidChangeListener { [weak self] res, user in
                guard let self = self else { return }
                self.state = user == nil ? .loggedOut : .loggedIn
                
                if let uid = user?.uid {
                    self.handleRefresh(with: uid)
                }
            }
    }
    
    func handleRefresh(with uid: String) {
        // Store the database handle for cleanup later
        databaseHandle = Database
            .database()
            .reference()
            .child("users")
            .child(uid)
            .observe(.value) { [weak self] snapshot in
                guard let self = self,
                      let value = snapshot.value as? NSDictionary,
                      let username = value[RegistrationKeys.username.rawValue] as? String else{
                    return
                }
                
                DispatchQueue.main.async {
                    self.userDetails = SessionUserDetails(username: username)
                }
            }
    }
}

Fix 2: Improve Alert State Handling

Your current alert logic directly accesses vm.state inside the alert closure, which can lead to race conditions. Instead, add a dedicated published property for error messages in your RegistrationViewModelImpl:

final class RegistrationViewModelImpl: ObservableObject, RegistrationViewModel {
    @Published var hasError: Bool = false
    @Published var state: RegistrationState = .na
    @Published var errorMessage: String? // Add this
    let service: RegistrationService
    var userDetails: RegistrationDetails = RegistrationDetails.new
    private var subscriptions = Set<AnyCancellable>()
    
    init(service: RegistrationService) {
        self.service = service
        setupErrorSubscriptions()
    }
    
    // ... existing register() method ...
}

private extension RegistrationViewModelImpl {
    func setupErrorSubscriptions() {
        $state
            .map { state -> (Bool, String?) in
                switch state {
                case .successfull, .na:
                    return (false, nil)
                case .failed(let error):
                    return (true, error.localizedDescription)
                }
            }
            .sink { [weak self] hasError, message in
                self?.hasError = hasError
                self?.errorMessage = message
            }
            .store(in: &subscriptions)
    }
}

Then update your RegisterView alert to use this safer property:

.alert(isPresented: $vm.hasError, content: {
    Alert(
        title: Text("Error"),
        message: Text(vm.errorMessage ?? "Something went wrong")
    )
})

Final Steps to Ensure Fix

  1. Clean your project build folder (press Cmd+Shift+K in Xcode) to clear any cached artifacts from the duplicate class definition.
  2. Rebuild and run your app—this should resolve the EXC_BAD_ACCESS crash immediately.
  3. Double-check that your GoogleService-Info.plist is properly added to your project and assigned to the correct target.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 06:54:07