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

Swift4新手求助:如何在ViewController中使用AppDelegate里的变量?

嘿,作为Swift新手碰到这种跨组件传值的问题太正常啦!我给你分享几个项目里常用的解决方案,你可以根据自己的场景选:

方法一:用通知中心(NotificationCenter)传递

这是轻量跨组件传值的首选,步骤很清晰:

  1. 在AppDelegate拿到Token后发送通知:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    if let refreshedToken = InstanceID.instanceID().token() {
        print("InstanceID token: \(refreshedToken)")
        // 发送携带Token的通知
        NotificationCenter.default.post(
            name: NSNotification.Name("DidReceiveFCMToken"),
            object: nil,
            userInfo: ["fcmToken": refreshedToken]
        )
    }
}
  1. 在ViewController里监听通知并处理:
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 注册通知监听
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleFCMTokenReceived(_:)),
            name: NSNotification.Name("DidReceiveFCMToken"),
            object: nil
        )
    }

    // 处理Token的方法
    @objc private func handleFCMTokenReceived(_ notification: Notification) {
        if let token = notification.userInfo?["fcmToken"] as? String {
            // 这里就可以用Token啦
            print("拿到FCM Token:\(token)")
        }
    }

    // 页面销毁时移除监听,避免内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

方法二:用单例类存储Token

如果Token是全局需要用到的,单例会是很方便的选择:

  1. 创建一个单例管理类TokenManager.swift:
class TokenManager {
    // 全局唯一实例
    static let shared = TokenManager()
    // 存储FCM Token的变量
    var fcmToken: String?
    
    // 私有化构造方法,确保只能通过shared获取实例
    private init() {}
}
  1. 在AppDelegate里给单例赋值:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    if let refreshedToken = InstanceID.instanceID().token() {
        print("InstanceID token: \(refreshedToken)")
        TokenManager.shared.fcmToken = refreshedToken
    }
}
  1. 在ViewController里随时获取:
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 直接从单例取Token,记得判空
        if let token = TokenManager.shared.fcmToken {
            print("从单例拿到的Token:\(token)")
        }
    }
}

小贴士:如果需要重启App后还能拿到Token,可以把它存在UserDefaults里,在单例里加个存/取的方法就行~

方法三:用闭包回调传递

如果你的ViewController是在AppDelegate之后初始化的,闭包也是个不错的选择:

  1. 在ViewController里定义闭包属性:
class ViewController: UIViewController {
    // 定义接收Token的闭包
    var onTokenReceived: ((String) -> Void)?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置闭包的处理逻辑
        onTokenReceived = { [weak self] token in
            guard let self = self else { return }
            print("通过闭包拿到的Token:\(token)")
            // 在这里处理你的Token逻辑
        }
    }
}
  1. 在AppDelegate里拿到Token后调用闭包:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    if let refreshedToken = InstanceID.instanceID().token() {
        print("InstanceID token: \(refreshedToken)")
        // 假设根控制器是你的ViewController,实际根据页面结构调整
        if let rootVC = window?.rootViewController as? ViewController {
            rootVC.onTokenReceived?(refreshedToken)
        }
    }
}

注意:闭包要加[weak self]避免循环引用哦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:39:29