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

iOS Swift:UITabBarController内视图控制器双向传值首次点击失效问题

问题分析与修复方案

你猜的完全没错!核心问题就是观察者的注册时机晚于通知的发送时机,导致首次点击Profile标签时,通知已经发出去了,但Profile控制器还没来得及注册观察者,自然收不到事件。

具体流程拆解

首次点击Profile标签时的执行顺序是:

  1. tabBarController(_:shouldSelect:) 触发,Home控制器发送通知
  2. Profile控制器被初始化,执行viewDidLoad(如果是第一次创建)
  3. Profile控制器的视图显示,执行viewDidAppear

你之前把观察者注册放在viewDidAppear里,这时候通知已经在第一步发送完了,所以changeCounts根本不会被调用。


修复步骤

1. 提前注册观察者

把Profile控制器里的观察者注册移到更早的生命周期方法,比如viewDidLoad,这个方法在控制器创建后立即执行,早于通知发送的时机:

override func viewDidLoad() {
    super.viewDidLoad()
    // 在这里注册观察者,确保通知发送前已经完成注册
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(changeCounts),
        name: NSNotification.Name("com.rjt.Chao.mypostnumbercount"),
        object: nil
    )
}

// 务必添加deinit方法移除观察者,避免内存泄漏
deinit {
    NotificationCenter.default.removeObserver(self)
}

2. 优化代码安全性

  • 避免强制解包,在changeCounts里用更安全的类型转换:
@objc func changeCounts(notification: Notification) {
    guard let count = notification.userInfo?["currentUserPostCount"] as? Int else {
        print("无法解析帖子数量")
        return
    }
    posts.setTitle("\(count)", for: .normal)
}
  • 用extension定义通知名称,避免字符串拼写错误:
extension Notification.Name {
    static let myPostNumberCount = Notification.Name("com.rjt.Chao.mypostnumbercount")
    static let postsClicked = Notification.Name("com.rjt.Chao.postsCliked")
}

之后使用时直接写.myPostNumberCount,比如:

// Home控制器发送通知
NotificationCenter.default.post(
    name: .myPostNumberCount,
    object: self,
    userInfo: ["currentUserPostCount": count]
)

// Profile控制器注册观察者
NotificationCenter.default.addObserver(
    self,
    selector: #selector(changeCounts),
    name: .myPostNumberCount,
    object: nil
)

更优雅的双向数据传递方案

虽然NotificationCenter能解决问题,但对于两个TabBar控制器之间的直接数据传递,还有更合适的方案:

  • 共享ViewModel:创建一个单例或注入的PostDataViewModel,用@Published属性(Combine框架)存储帖子数量,两个控制器都订阅这个属性的变化,自动更新UI。
  • Delegate模式:让TabBarController作为中间代理,或者两个控制器互相持有weak delegate引用,直接调用方法传递数据。
  • 闭包回调:在Profile控制器初始化时,传入一个获取帖子数量的闭包,或者Home控制器把更新数量的闭包传给Profile。

这些方案比NotificationCenter更直接,也更容易维护和调试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:55:39