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

如何在AppDelegate外处理UIApplicationDidRegisterToRemoteNotificationsWithDeviceToken?

Great question! Since you're building an iOS framework, it makes total sense to decouple APNs token handling from the host app's AppDelegate—here are a few clean, framework-friendly approaches to pull this off:


1. Use NotificationCenter to Broadcast the Token

This is a low-coupling approach that lets any part of your framework listen for the token once it's received.

First, update the host app's AppDelegate to broadcast the token via a notification:

// In the host app's AppDelegate
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Convert token to a valid string (avoid using .description directly!)
    let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    
    // Post a notification with the token
    NotificationCenter.default.post(
        name: .apnsDeviceTokenReceived,
        object: nil,
        userInfo: ["token": tokenString]
    )
}

// Define a reusable notification name (you can put this in your framework)
extension Notification.Name {
    static let apnsDeviceTokenReceived = Notification.Name("APNsDeviceTokenReceived")
}

Then, in your framework, create a handler class to listen for this notification:

class FrameworkAPNsHandler {
    init() {
        // Start listening when the handler is initialized
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleTokenReceived(_:)),
            name: .apnsDeviceTokenReceived,
            object: nil
        )
    }
    
    @objc private func handleTokenReceived(_ notification: Notification) {
        guard let token = notification.userInfo?["token"] as? String else { return }
        // Do your framework-specific logic with the token here
        print("Framework received APNs token: \(token)")
    }
    
    // Clean up the observer to avoid memory leaks
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

2. Use a Custom Delegate Pattern (Structured & Scalable)

If you want more control over who receives the token, a delegate pattern is a cleaner, more intentional choice for framework code.

First, create a singleton manager in your framework:

// In your framework
protocol APNsManagerDelegate: AnyObject {
    func apnsManager(_ manager: APNsManager, didReceiveDeviceToken token: String)
}

class APNsManager {
    static let shared = APNsManager()
    weak var delegate: APNsManagerDelegate?
    
    private init() {} // Enforce singleton
    
    // Call this from the host app's AppDelegate
    func processDeviceToken(_ deviceToken: Data) {
        let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
        delegate?.apnsManager(self, didReceiveDeviceToken: tokenString)
    }
}

Update the host app's AppDelegate to forward the token to your manager:

// In host app's AppDelegate
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    APNsManager.shared.processDeviceToken(deviceToken)
}

Then, in your framework, have your service class conform to the delegate:

class FrameworkCoreService: APNsManagerDelegate {
    init() {
        APNsManager.shared.delegate = self
    }
    
    func apnsManager(_ manager: APNsManager, didReceiveDeviceToken token: String) {
        // Handle token logic for your framework
        print("Framework core service got token: \(token)")
    }
}

3. Use Closure Callbacks (Simple for Single Use Cases)

If your framework only needs one place to handle the token, a closure is the most concise option.

Update your framework's APNs manager to use a closure:

// In your framework
class APNsManager {
    static let shared = APNsManager()
    var onTokenReceived: ((String) -> Void)?
    
    private init() {}
    
    func processDeviceToken(_ deviceToken: Data) {
        let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
        onTokenReceived?(tokenString)
    }
}

Then, in your framework's service class, set the closure:

class FrameworkNotificationService {
    init() {
        APNsManager.shared.onTokenReceived = { token in
            // Handle token here
            print("Framework notification service received token: \(token)")
        }
    }
}

Key Reminders for Framework Development:

  • Token Conversion: Never use deviceToken.description to get the token string—it includes extra characters like < and > that will break APNs requests. Stick with the map + joined method shown above.
  • Host App Docs: Make sure to tell your framework users they need to call your APNsManager method from their AppDelegate (or SceneDelegate, for scene-based apps) callback.
  • Permissions: The host app still needs to request push notification permissions using UNUserNotificationCenter.current().requestAuthorization(...) before registering for remote notifications.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:22:55