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

如何像WhatsApp一样禁用TableView且不遮挡全屏?(SearchController场景)

解决Xcode9.3+Swift4中SearchController仅暗化TableView的问题

我刚好在Xcode9.3+Swift4环境下处理过类似WhatsApp的搜索栏需求,默认的UISearchController确实会有全屏遮罩的问题,哪怕设置obscuresBackgroundDuringPresentation = false也没法直接实现只暗化TableView的效果。给你两个靠谱的解决方案:

方案一:自定义半透明遮罩(推荐,稳定可控)

这个方法完全不依赖系统私有逻辑,通过手动添加一个仅覆盖TableView的半透明视图,配合搜索栏文本变化来控制遮罩显示/隐藏以及TableView交互状态。

步骤与代码实现

  1. 定义变量:在你的ViewController中添加遮罩视图和SearchController的引用
import UIKit

class YourViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    private var tableViewDimmingView: UIView!
    private let searchController = UISearchController(searchResultsController: nil)
    
    // ... 其他业务代码
}
  1. 初始化遮罩与配置SearchController:在viewDidLoad中完成视图设置
override func viewDidLoad() {
    super.viewDidLoad()
    
    // 初始化半透明遮罩,仅覆盖TableView区域
    tableViewDimmingView = UIView()
    tableViewDimmingView.backgroundColor = UIColor.black.withAlphaComponent(0.3)
    tableViewDimmingView.isHidden = true
    tableViewDimmingView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(tableViewDimmingView)
    
    // 用AutoLayout绑定遮罩到TableView的四个边缘,适配布局变化
    NSLayoutConstraint.activate([
        tableViewDimmingView.topAnchor.constraint(equalTo: tableView.topAnchor),
        tableViewDimmingView.leadingAnchor.constraint(equalTo: tableView.leadingAnchor),
        tableViewDimmingView.trailingAnchor.constraint(equalTo: tableView.trailingAnchor),
        tableViewDimmingView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor)
    ])
    
    // 配置SearchController,关闭默认全屏遮罩
    searchController.searchResultsUpdater = self
    searchController.obscuresBackgroundDuringPresentation = false
    searchController.hidesNavigationBarDuringPresentation = false // 按需保留导航栏
    navigationItem.searchController = searchController
    definesPresentationContext = true
    
    // 监听搜索栏文本变化事件
    searchController.searchBar.addTarget(self, action: #selector(searchBarTextChanged(_:)), for: .editingChanged)
}
  1. 实现文本变化与搜索更新逻辑:控制遮罩和TableView交互状态
@objc private func searchBarTextChanged(_ searchBar: UISearchBar) {
    updateDimmingViewState(isSearchEmpty: searchBar.text?.isEmpty ?? true)
}

extension YourViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        updateDimmingViewState(isSearchEmpty: searchController.searchBar.text?.isEmpty ?? true)
    }
}

// 封装状态更新逻辑,避免重复代码
private func updateDimmingViewState(isSearchEmpty: Bool) {
    tableViewDimmingView.isHidden = !isSearchEmpty
    tableView.isUserInteractionEnabled = !isSearchEmpty
}

方案二:修改系统默认遮罩的Frame(适配性稍弱)

如果不想自定义遮罩,可以尝试找到UISearchController自带的背景遮罩视图,修改它的Frame使其仅覆盖TableView。不过这个方法依赖系统视图层级,不同iOS版本可能有变化,仅做备选参考。

代码实现

在viewDidAppear或SearchController的presentation回调中修改遮罩Frame:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    // 遍历SearchController的子视图,找到全屏背景遮罩
    if let backgroundMask = searchController.view.subviews.first(where: {
        $0.backgroundColor != nil && $0.frame == view.bounds
    }) {
        // 将遮罩Frame改为TableView的范围
        backgroundMask.frame = tableView.bounds
        backgroundMask.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    }
}

注意事项

  • 方案一的AutoLayout绑定能更好适配屏幕旋转、TableView布局变化等场景,优先推荐。
  • 如果你的TableView有导航栏或其他顶部视图,要确保遮罩不会覆盖这些区域,调整约束即可。

内容的提问来源于stack exchange,提问作者Oséias Ribeiro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:48:22