点击导航栏返回按钮后,如何从另一个ViewController隐藏/禁用按钮
嘿,我完全懂你现在卡在哪了——从训练项目选择页面返回后,想把计划页面里对应日期的按钮给禁用或者隐藏,但试了好多次都没成功对吧?别慌,我给你几个iOS开发里常用的解决方案,肯定能帮你搞定:
方法一:用闭包(Closure)传递状态
这是最轻便的方式,适合页面间简单的状态传递逻辑。核心思路是在第二个页面定义一个闭包,保存或返回时调用闭包把选中的日期传回去,第一个页面提前在闭包里写好更新按钮的逻辑。
第二个页面(训练项目选择VC)代码:
class TrainingSelectionVC: UIViewController { // 定义闭包,参数是选中的日期索引(比如1-7) var onSaveAndBack: ((Int) -> Void)? // 记录用户点击的是第几天的按钮 var selectedDayIndex: Int? // 用户点击自定义保存按钮的方法 @IBAction func saveButtonTapped(_ sender: UIButton) { // 先处理保存训练项目的逻辑 // ... // 调用闭包传递日期索引 if let index = selectedDayIndex { onSaveAndBack?(index) } // 手动返回上一页 navigationController?.popViewController(animated: true) } // 处理用户直接点导航栏返回的情况 override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 判断是否是因为pop回上一页而消失 if isMovingFromParent { if let index = selectedDayIndex { onSaveAndBack?(index) } } } }
第一个页面(训练计划VC)代码:
class TrainingPlanVC: UIViewController { // 点击日期按钮跳转的方法 @IBAction func dayButtonTapped(_ sender: UIButton) { let selectionVC = storyboard?.instantiateViewController(withIdentifier: "TrainingSelectionVC") as! TrainingSelectionVC // 用按钮的tag来标记日期索引(提前给7个按钮设置好tag:1-7) selectionVC.selectedDayIndex = sender.tag // 设置闭包,返回后更新按钮状态 selectionVC.onSaveAndBack = { [weak self] dayIndex in guard let self = self else { return } // 找到对应tag的按钮,修改状态 if let targetButton = self.view.viewWithTag(dayIndex) as? UIButton { targetButton.isEnabled = false // 禁用按钮 // 或者 targetButton.isHidden = true // 隐藏按钮 } } navigationController?.pushViewController(selectionVC, animated: true) } }
注意一定要用[weak self]来避免循环引用哦!
方法二:代理模式(Delegate)
如果你的页面交互逻辑比较复杂,代理模式会让代码结构更清晰,耦合性更低。
第一步:定义代理协议
protocol TrainingSelectionDelegate: AnyObject { func didSaveTraining(forDay dayIndex: Int) }
第二个页面(训练项目选择VC)代码:
class TrainingSelectionVC: UIViewController { weak var delegate: TrainingSelectionDelegate? var selectedDayIndex: Int? @IBAction func saveButtonTapped(_ sender: UIButton) { // 保存逻辑... if let index = selectedDayIndex { delegate?.didSaveTraining(forDay: index) } navigationController?.popViewController(animated: true) } // 处理导航栏返回的情况 override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParent { if let index = selectedDayIndex { delegate?.didSaveTraining(forDay: index) } } } }
第一个页面(训练计划VC)代码:
class TrainingPlanVC: UIViewController, TrainingSelectionDelegate { @IBAction func dayButtonTapped(_ sender: UIButton) { let selectionVC = storyboard?.instantiateViewController(withIdentifier: "TrainingSelectionVC") as! TrainingSelectionVC selectionVC.selectedDayIndex = sender.tag // 设置代理 selectionVC.delegate = self navigationController?.pushViewController(selectionVC, animated: true) } // 实现代理方法,更新按钮状态 func didSaveTraining(forDay dayIndex: Int) { if let targetButton = view.viewWithTag(dayIndex) as? UIButton { targetButton.isEnabled = false } } }
方法三:通知中心(NotificationCenter)
如果两个页面的层级关系比较远,或者你不想直接关联两个VC,可以用通知中心,但要注意它的耦合性较高,尽量少用。
第二个页面(训练项目选择VC)代码:
@IBAction func saveButtonTapped(_ sender: UIButton) { // 保存逻辑... if let index = selectedDayIndex { // 发送通知,携带日期索引 NotificationCenter.default.post( name: NSNotification.Name("DidSaveTraining"), object: nil, userInfo: ["dayIndex": index] ) } navigationController?.popViewController(animated: true) }
第一个页面(训练计划VC)代码:
class TrainingPlanVC: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 注册通知监听 NotificationCenter.default.addObserver( self, selector: #selector(updateDayButton(_:)), name: NSNotification.Name("DidSaveTraining"), object: nil ) } @objc func updateDayButton(_ notification: Notification) { // 从通知里取出日期索引,更新按钮 if let dayIndex = notification.userInfo?["dayIndex"] as? Int, let targetButton = view.viewWithTag(dayIndex) as? UIButton { targetButton.isEnabled = false } } // 记得销毁页面时移除观察者,避免内存泄漏 deinit { NotificationCenter.default.removeObserver(self) } }
这三种方法都能解决你的问题,你可以根据自己项目的复杂度选最适合的~
内容的提问来源于stack exchange,提问作者Noe Holguin
相关产品推荐
相关产品推荐

