如何给UIBarButtonItem加自定义动作及实现VC3直接返回VC1?
这里有几种常用的实现方式,你可以根据自己的需求来选:
- 直接通过初始化方法绑定动作
如果只是用系统样式的文字或图标按钮,初始化时就能直接指定触发对象和动作:
接着实现对应的触发方法就行,注意要加// 文字按钮示例 let customTextButton = UIBarButtonItem(title: "自定义", style: .plain, target: self, action: #selector(customTextButtonTapped)) // SF Symbol图标按钮示例 let customIconButton = UIBarButtonItem(image: UIImage(systemName: "plus"), style: .plain, target: self, action: #selector(customIconButtonTapped)) // 将按钮添加到导航栏右侧 navigationItem.rightBarButtonItem = customTextButton@objc标记:@objc func customTextButtonTapped() { // 这里写你的自定义逻辑 print("文字按钮被点击啦") } @objc func customIconButtonTapped() { print("图标按钮被点击啦") } - 自定义UIButton作为UIBarButtonItem的视图
如果需要更复杂的样式(比如自定义背景色、圆角、文字渐变),可以先做一个UIButton,再把它包装成UIBarButtonItem:
对应的触发方法:let customStyleButton = UIButton(type: .system) customStyleButton.setTitle("专属样式", for: .normal) customStyleButton.setTitleColor(.orange, for: .normal) customStyleButton.layer.cornerRadius = 6 customStyleButton.frame = CGRect(x: 0, y: 0, width: 80, height: 30) customStyleButton.addTarget(self, action: #selector(customStyleButtonTapped), for: .touchUpInside) let barButtonItem = UIBarButtonItem(customView: customStyleButton) navigationItem.leftBarButtonItem = barButtonItem@objc func customStyleButtonTapped() { // 执行你的自定义逻辑 } - 小提醒
动作方法必须带@objc,因为UIBarButtonItem的动作依赖Objective-C runtime识别;另外要确保target设置的是正确的对象(比如当前视图控制器的self)。
2. 实现VC3返回直接回到VC1
针对你说的VC1→VC2→VC3的导航流程,要让VC3点返回直接跳回VC1,有几种靠谱的方法:
方法一:自定义返回按钮,用popToViewController跳转
这种方式最直观,也最可控:
步骤1:替换VC3的系统返回按钮
在VC3的viewDidLoad里自定义返回按钮样式:
override func viewDidLoad() { super.viewDidLoad() // 创建自定义返回按钮,也可以用系统的返回图标 let backToVC1Button = UIBarButtonItem(title: "返回首页", style: .plain, target: self, action: #selector(backToVC1Action)) navigationItem.leftBarButtonItem = backToVC1Button }
步骤2:实现返回逻辑
遍历导航栈找到VC1的实例,直接跳转回去:
@objc func backToVC1Action() { // 从导航栈中筛选出HomeViewController类型的实例 if let vc1 = navigationController?.viewControllers.first(where: { $0 is HomeViewController }) { navigationController?.popToViewController(vc1, animated: true) } else { // 找不到VC1的话,默认退回到上一页作为兜底 navigationController?.popViewController(animated: true) } }
方法二:如果VC1是根控制器,用popToRootViewController
要是VC1刚好是UINavigationController的根控制器,那代码可以更简单:
@objc func backToVC1Action() { navigationController?.popToRootViewController(animated: true) }
方法三:跳转时移除VC2(隐藏返回VC2的路径)
如果你希望从VC2跳转到VC3时,直接把VC2从导航栈里删掉,这样系统默认的返回按钮就会直接回到VC1。在VC2的didSelectItemAt代理方法里这么写:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let vc3 = NewViewController2() // 获取当前导航栈,保留到VC1的部分,再加上VC3 if let currentStack = navigationController?.viewControllers, let vc2Index = currentStack.firstIndex(of: self) { var newStack = currentStack[0...vc2Index] newStack.removeLast() // 移除VC2 newStack.append(vc3) navigationController?.setViewControllers(Array(newStack), animated: true) } }
这种方式的好处是不用修改VC3的返回按钮,缺点是跳转动画还是push,但导航栈里已经没有VC2了。
内容的提问来源于stack exchange,提问作者Venkatesh Chejarla
相关产品推荐
相关产品推荐

