Swift中为模态展示的UICollectionViewController添加返回按钮的方法
给模态展示的UICollectionViewController添加返回按钮的方案
嘿,这个问题其实很常见——模态出来的UICollectionViewController默认没有自带导航栏,所以自然不会有返回按钮。下面给你几个靠谱的解决方案,从符合iOS设计规范的常规做法到灵活自定义的选项都有:
方案1:给模态控制器包裹UINavigationController(最推荐)
这是iOS开发里最标准的做法,给你的FriendsRequestsController套一层导航控制器,然后在导航栏添加返回按钮。
修改你的presentFRC方法:
func presentFRC() { let requestsVC = FriendsRequestsController(collectionViewLayout: UICollectionViewFlowLayout()) // 用UINavigationController包裹目标控制器 let navController = UINavigationController(rootViewController: requestsVC) // 可以在present前给目标控制器设置返回按钮,也可以在requestsVC内部设置 requestsVC.navigationItem.leftBarButtonItem = UIBarButtonItem( title: "返回", style: .plain, target: self, action: #selector(dismissModalController) ) present(navController, animated: true) } // 实现dismiss方法 @objc private func dismissModalController() { dismiss(animated: true) }
或者更推荐在FriendsRequestsController的viewDidLoad里自行设置返回按钮,这样控制器的职责更清晰:
class FriendsRequestsController: UICollectionViewController { override func viewDidLoad() { super.viewDidLoad() // 开启导航栏(默认是开启的,但可以显式设置确保) navigationController?.isNavigationBarHidden = false // 添加返回按钮 navigationItem.leftBarButtonItem = UIBarButtonItem( title: "返回", style: .plain, target: self, action: #selector(handleBackTap) ) } @objc private func handleBackTap() { dismiss(animated: true) } }
方案2:在自定义UICollectionViewHeader中添加返回按钮
既然你的主控制器用到了UserProfileHeaderDelegate这类代理,说明你可能习惯用自定义header做交互。那可以直接在FriendsRequestsController的collectionView header里加返回按钮,通过代理通知控制器关闭模态:
首先定义header的代理协议:
protocol RequestsHeaderDelegate: AnyObject { func didTapBackButton() } class RequestsHeader: UICollectionReusableView { weak var delegate: RequestsHeaderDelegate? override init(frame: CGRect) { super.init(frame: frame) // 创建返回按钮并布局 let backButton = UIButton(type: .system) backButton.setTitle("返回", for: .normal) backButton.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium) backButton.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside) addSubview(backButton) // 这里用frame简化布局,实际项目推荐AutoLayout backButton.frame = CGRect(x: 20, y: 20, width: 60, height: 30) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } @objc private func backButtonTapped() { delegate?.didTapBackButton() } }
然后在FriendsRequestsController中实现代理:
extension FriendsRequestsController: RequestsHeaderDelegate { func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "RequestsHeader", for: indexPath) as! RequestsHeader header.delegate = self return header } func didTapBackButton() { dismiss(animated: true) } }
方案3:添加全屏滑动返回手势
如果想让用户像使用导航控制器侧滑返回一样操作,可以给模态的视图添加右滑手势:
func presentFRC() { let requestsVC = FriendsRequestsController(collectionViewLayout: UICollectionViewFlowLayout()) let navController = UINavigationController(rootViewController: requestsVC) // 添加右滑返回手势 let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(dismissModalController)) swipeGesture.direction = .right navController.view.addGestureRecognizer(swipeGesture) present(navController, animated: true) } @objc private func dismissModalController() { dismiss(animated: true) }
方案4:在视图角落添加自定义关闭按钮
如果不需要导航栏,想做更简洁的界面,可以直接在FriendsRequestsController的view上添加一个关闭按钮:
class FriendsRequestsController: UICollectionViewController { override func viewDidLoad() { super.viewDidLoad() let closeButton = UIButton(type: .system) closeButton.setTitle("×", for: .normal) closeButton.titleLabel?.font = UIFont.systemFont(ofSize: 24, weight: .bold) closeButton.addTarget(self, action: #selector(handleCloseTap), for: .touchUpInside) view.addSubview(closeButton) // AutoLayout布局示例 closeButton.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ closeButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10), closeButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15) ]) } @objc private func handleCloseTap() { dismiss(animated: true) } }
每个方案适用场景不同:方案1最符合iOS设计语言,适合大多数情况;方案2适合你的控制器已经依赖自定义header做交互的场景;方案3能提升用户体验;方案4适合追求极简界面的需求。
内容的提问来源于stack exchange,提问作者user9585671
相关产品推荐
相关产品推荐

