如何在ControllerOne收到通知时显示ControllerTwo中的按钮?
实现WebSocket通知触发ControllerTwo按钮显示的几种方案
这里有几种靠谱的方案帮你搞定这个需求,我结合你的现有代码给你详细拆解:
方案一:使用NotificationCenter(推荐,低耦合)
这是iOS里跨组件通信的常用方式,不需要两个控制器直接持有引用,耦合度很低,适合你这种场景。
步骤1:在NewDashboardViewController里注册通知监听
修改你的ControllerTwo.swift代码,在视图加载时注册一个自定义通知,收到通知后就显示按钮,同时记得在控制器销毁时移除观察者避免内存泄漏:
class NewDashboardViewController: UIViewController, UITableViewDataSource, UITabBarControllerDelegate, UITableViewDelegate { @IBOutlet weak var showNotificationsbtn: UIButton! override func viewDidLoad() { super.viewDidLoad() // 注册通知,监听"显示通知按钮"的事件 NotificationCenter.default.addObserver( self, selector: #selector(showNotificationButton), name: NSNotification.Name("ShowNotificationButtonEvent"), object: nil ) // 初始状态隐藏按钮 showNotificationsbtn.isHidden = true } // 收到通知后执行的方法,显示按钮 @objc private func showNotificationButton() { showNotificationsbtn.isHidden = false } @IBAction func showNotifications(_ sender: Any) { showNotificationsbtn.isHidden = true // 注意:手动调用viewDidAppear(true)不太规范,这是系统的生命周期方法,建议换成你实际需要的操作 // 比如如果要刷新表格,就写 tableView.reloadData() } // 控制器销毁时移除观察者,防止内存泄漏 deinit { NotificationCenter.default.removeObserver(self) } }
步骤2:在ControllerOne的WebSocket回调里发送通知
修改ControllerOne.swift的websocket方法,当满足selectedIndex == 0的条件时,发送刚才定义的通知:
public func websocket(token: Any){ self.ws.open("ws://"+String(APIHOST)+":"+String(port)+"/ws?token="+String(describing: token)) self.ws.event.message = { message in let res = self.convertToDictionary(text: message as! String) guard let hasNotification = res?["notification"], hasNotification != nil else { return } self.count_total_notifications_ws = (self.count_total_notifications_ws ?? 0) + 1 let presentView = UIApplication.shared.keyWindow?.rootViewController?.presentedViewController as? SWRevealViewController let tabbarController = presentView?.frontViewController as? UITabBarController if let tabbar = tabbarController { if tabbar.selectedIndex != 0 { tabbar.tabBarItems?[0].badgeValue = "\(self.count_total_notifications_ws ?? 0)" } else { // 发送通知,触发NewDashboardViewController显示按钮 NotificationCenter.default.post( name: NSNotification.Name("ShowNotificationButtonEvent"), object: nil ) } } } }
方案二:直接获取NewDashboardViewController实例操作UI
这种方式更直接,但依赖你的页面层级结构,如果后续页面结构变化可能需要调整代码。
修改ControllerOne.swift里的else分支,直接找到当前显示的NewDashboardViewController实例,然后更新按钮状态(注意UI操作必须在主线程):
public func websocket(token: Any){ self.ws.open("ws://"+String(APIHOST)+":"+String(port)+"/ws?token="+String(describing: token)) self.ws.event.message = { message in let res = self.convertToDictionary(text: message as! String) guard let hasNotification = res?["notification"], hasNotification != nil else { return } self.count_total_notifications_ws = (self.count_total_notifications_ws ?? 0) + 1 let presentView = UIApplication.shared.keyWindow?.rootViewController?.presentedViewController as? SWRevealViewController let tabbarController = presentView?.frontViewController as? UITabBarController if let tabbar = tabbarController { if tabbar.selectedIndex != 0 { tabbar.tabBarItems?[0].badgeValue = "\(self.count_total_notifications_ws ?? 0)" } else { // 根据你的页面层级获取NewDashboardViewController实例 if let navVC = tabbar.selectedViewController as? UINavigationController { // 如果是嵌套在导航控制器里 if let dashboardVC = navVC.rootViewController as? NewDashboardViewController { DispatchQueue.main.async { dashboardVC.showNotificationsbtn.isHidden = false } } } else { // 如果直接是tabbar的子控制器 if let dashboardVC = tabbar.selectedViewController as? NewDashboardViewController { DispatchQueue.main.async { dashboardVC.showNotificationsbtn.isHidden = false } } } } } } }
注意事项
- 所有UI操作必须在主线程执行,WebSocket的回调一般在子线程,所以一定要用
DispatchQueue.main.async包裹UI修改代码,避免崩溃。 - 方案一的通知名称建议用唯一的字符串,比如加上你的项目前缀,防止和其他第三方库的通知冲突。
内容的提问来源于stack exchange,提问作者NelbeDG
相关产品推荐
相关产品推荐

