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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:36:10