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

iOS Swift中注销后如何调用AppDelegate并重新注册FCM Token?

Hey there, let's tackle your FCM token issue and the AppDelegate question one by one—this is a common gotcha with Firebase Cloud Messaging on iOS, so I’ve got you covered!

Fixing the FCM Token Re-registration Issue After Logout

First, let’s break down why you can’t re-register the FCM token after logout:

  • You’re only deleting the token from your backend, but Firebase still holds the old token locally. Without telling Firebase to invalidate it, it won’t generate a new token automatically.
  • Your current setup relies solely on a notification to receive the token, but if the token isn’t refreshed (because Firebase thinks it’s still valid), that notification never fires.
  • You’re adding the same notification observer twice (in viewDidLoad and viewDidAppear), which can lead to duplicate calls and unexpected behavior.

Here’s how to fix it:

1. Properly Invalidate the FCM Token During Logout

When the user logs out, don’t just call your backend API—also tell Firebase to delete the local token. Add this to your logout flow:

import FirebaseMessaging

func handleLogout() {
    // 1. Call your backend API to delete the token
    // ... your existing backend call here ...
    
    // 2. Invalidate Firebase's local token
    Messaging.messaging().deleteToken { error in
        if let error = error {
            print("Failed to delete FCM token: \(error.localizedDescription)")
        } else {
            print("FCM token deleted successfully")
        }
    }
    
    // 3. Navigate to login screen
    // ... your navigation code here ...
}

2. Optimize Token Fetching in LoginViewController

Instead of waiting passively for a notification, actively request the token when the login screen loads. Also, fix the duplicate observer issue:

var fcmval: String?
let baseURL = "https://url"

override func viewDidLoad() {
    super.viewDidLoad()
    // Add observer ONCE to catch token updates
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(fcmTokenUpdated(notification:)),
        name: Notification.Name("FCMToken"),
        object: nil
    )
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // Actively fetch the FCM token when the login screen appears
    fetchFCMToken()
}

@objc func fcmTokenUpdated(notification: Notification) {
    if let userInfo = notification.userInfo as? [String: String],
       let token = userInfo["token"] {
        updateFCMToken(token: token)
    }
}

private func fetchFCMToken() {
    Messaging.messaging().token { [weak self] token, error in
        guard let self = self else { return }
        if let error = error {
            print("Error fetching FCM token: \(error.localizedDescription)")
            return
        }
        if let token = token {
            self.updateFCMToken(token: token)
        }
    }
}

private func updateFCMToken(token: String) {
    self.fcmval = token
    print("FCM token received: \(token)")
    // Update your login view with the token
    A8FlowBuilder(self).showLoginView(url: baseURL, fcm: token)
}

3. Handle Asynchronous Token Fetching

Since fetching the token is async, make sure your login flow doesn’t proceed until the token is available. If your login button triggers the API call directly, add a check:

@IBAction func loginButtonTapped(_ sender: UIButton) {
    guard let token = fcmval else {
        // Show a loading state and fetch the token first
        fetchFCMToken()
        return
    }
    // Proceed with login API call using the token
}

Calling AppDelegate Methods After Logout

There are two clean ways to trigger code in AppDelegate.swift after logout:

Option 1: Directly Reference AppDelegate

If you need to call a specific method, you can access the AppDelegate instance directly:

// In your logout handler
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
    appDelegate.handlePostLogoutCleanup()
}

Then add the method to AppDelegate.swift:

@objc func handlePostLogoutCleanup() {
    // Perform cleanup tasks (e.g., reset app state, clear cached data)
    do {
        try Messaging.messaging().deleteToken()
    } catch {
        print("Error deleting token in AppDelegate: \(error)")
    }
}

Option 2: Use NotificationCenter (More Decoupled)

For better separation of concerns, send a notification when the user logs out, and have AppDelegate listen for it:

  1. In AppDelegate.swift, add the observer in didFinishLaunchingWithOptions:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // ... other setup code ...
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handleLogoutNotification),
        name: Notification.Name("UserDidLogout"),
        object: nil
    )
    return true
}

@objc private func handleLogoutNotification() {
    handlePostLogoutCleanup()
}
  1. In your logout handler, post the notification:
func handleLogout() {
    // ... your logout logic ...
    NotificationCenter.default.post(name: Notification.Name("UserDidLogout"), object: nil)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:27:42