使用另一个视图控制器(带有表格视图)来显示 UISearchController 的结果

Posted

技术标签:

【中文标题】使用另一个视图控制器(带有表格视图)来显示 UISearchController 的结果【英文标题】:Using another view controller (with a table view) to show the results of UISearchController 【发布时间】:2018-04-25 13:54:20 【问题描述】:

我有两个视图控制器。第一个(CityViewController)包含一个搜索栏,所以它的配置在那里完成。第二个(CitySearchViewController)用于显示搜索结果(我需要自定义单元格,这就是为什么我不简单地使用UITableViewController)。这是在第一个视图控制器中配置search controller 的代码:

class CityViewController: UIViewController 

var searchController: UISearchController?

var citySearchViewController: CitySearchViewController?

override func viewDidLoad() 
    super.viewDidLoad()


    citySearchViewController = CitySearchViewController()
    searchController = UISearchController(searchResultsController: citySearchViewController)

    //Setting the search controller
    setSearchController()



//Setting the search controller
private func setSearchController() 
    if let searchController = searchController 
        searchController.searchResultsUpdater = citySearchViewController
        searchController.obscuresBackgroundDuringPresentation = true
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.searchBar.placeholder = "Search for a city"
        navigationItem.searchController = searchController
        definesPresentationContext = true
        searchController.searchBar.returnKeyType = .done
        //searchController.searchBar.enablesReturnKeyAutomatically = false
        searchController.searchBar.delegate = self

    
    




extension CityViewController: UISearchBarDelegate 
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) 
    searchController?.isActive = false
    
 

所以,我将我的第二个视图控制器 (CitySearchViewController) 设置为 searchResultsController。在里面我有一个城市数组,视图控制器是数据源和表视图的委托,它在里面。

这是视图控制器内的完整代码。

class CitySearchViewController: UIViewController 

@IBOutlet weak var tableView: UITableView! 
    didSet 
        tableView.delegate = self
        tableView.dataSource = self
    



  let cities = [City(name: "Saint Petersburg", coordinates: CLLocation(latitude: 59.93863, longitude: 30.31413)), City(name: "Moscow", coordinates: CLLocation(latitude: 55.75222, longitude: 37.61556)), City(name: "London", coordinates: CLLocation(latitude: 51.509865, longitude: -0.118092)), City(name: "Chicago", coordinates: CLLocation(latitude: 41.881832, longitude: -87.623177)), City(name: "Sochi", coordinates: CLLocation(latitude: 43.588348, longitude: 39.729996)), City(name: "Madrid", coordinates: CLLocation(latitude: 40.416775, longitude: -3.703790)), City(name: "New York", coordinates: CLLocation(latitude: 40.730610, longitude: -73.935242)), City(name: "Paris", coordinates: CLLocation(latitude: 48.864716, longitude: 2.349014)), City(name: "Amsterdam", coordinates: CLLocation(latitude: 52.370216, longitude: 4.895168)), City(name: "Barcelona", coordinates: CLLocation(latitude: 41.390205, longitude: 2.154007))]
var filteredCities = [City]()



override func viewDidLoad() 
    super.viewDidLoad()





private func filterContentForSearchText(_ searchText: String) 
    filteredCities = cities.filter( (city) -> Bool in
        return city.name.lowercased().contains(searchText.lowercased())
    )
    tableView.reloadData()

  

extension CitySearchViewController: UITableViewDataSource 

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return filteredCities.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "citySearchCell", for: indexPath) as! CitySearchTableViewCell
    let filteredCity = filteredCities[indexPath.row]
    cell.cityLabel.text = filteredCity.name

    return cell


 

extension CitySearchViewController: UITableViewDelegate 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
    return UITableViewAutomaticDimension
  
 

 extension CitySearchViewController: UISearchResultsUpdating 
func updateSearchResults(for searchController: UISearchController) 
    filterContentForSearchText(searchController.searchBar.text!)
 

在那里我进行了基本的表格视图设置,还过滤了数组并相应地更新了表格视图。

问题是,只要我开始在搜索栏中点击一个单词,就会出现异常。原因是CitySearchViewController里面的table view是nil。所以,我认为,在CityViewController 中的这行代码初始化视图控制器时,我做错了:

override func viewDidLoad() 
super.viewDidLoad()


citySearchViewController = CitySearchViewController()
searchController = UISearchController(searchResultsController: citySearchViewController)

//Setting the search controller
setSearchController()

我也尝试从情节提要中实例化视图控制器,但是,在这种情况下,我收到一个错误,指出在初始化期间使用的 storyboardId 没有视图控制器。我检查并重新检查了视图控制器的id,它与代码中使用的完全相同。这是我尝试从第一个 (CityViewController) 实例化 CitySearchViewController 的初始方式。

override func viewDidLoad() 
    super.viewDidLoad()

    citySearchViewController = UIStoryboard().instantiateViewController(withIdentifier: "searchCityTableView") as? CitySearchViewController

    //Setting the search controller
    setSearchController()

我没有使用另一个视图控制器来显示搜索控制器的结果,所以我想我做错了什么。

如果您知道我做错了什么或知道正确的做法,我将非常感谢您的帮助。

【问题讨论】:

【参考方案1】:

问题 #1

如果您通过以下方式初始化CitySearchViewController

citySearchViewController = CitySearchViewController()

这意味着它会跳过您在 Interface Builder 的情节提要中为该视图控制器设置的任何内容 - 最重要的是,将 IBOutlet 设置为您的 tableView

@IBOutlet weak var tableView: UITableView!

问题 #2

您还表明您尝试使用这行代码将其实例化为CitySearchViewController,但错误是找不到具有该标识符的VC:

citySearchViewController = UIStoryboard().instantiateViewController(withIdentifier: "searchCityTableView") as? CitySearchViewController

由于您没有指定故事板的名称来实例化 VC,因此可能是错误的。您需要将情节提要的名称指定为:

citySearchViewController = UIStoryboard(name: "<storyboard filename here>", bundle: nil).instantiateViewController(withIdentifier: "searchCityTableView") as? CitySearchViewController

(其中&lt;storyboard filename here&gt; 类似于“搜索”,用于名为“Search.storyboard”的情节提要)

【讨论】:

好的,现在我明白原因了,谢谢。正如我在问题中所说,我也尝试从情节提要中实例化它,但每次我收到关于 id 的错误时,我都检查了多次。任何想法为什么会发生这种情况? @TigranIskandaryan 是的,请参阅我的附加信息作为“问题 #2”的一部分 哦,这么愚蠢的错误...谢谢您的帮助,我会在堆栈允许时尽快接受您的回答:)

以上是关于使用另一个视图控制器(带有表格视图)来显示 UISearchController 的结果的主要内容,如果未能解决你的问题,请参考以下文章

使用表格视图快速搜索控制器滚动

如何在另一个视图控制器上向 UInavigationcontroller 显示完整的选定表格单元格

带有选项卡视图控制器的 Xcode IOS 转换视图

如何从 popoverpresentation 视图控制器导航到另一个视图控制器

将标签数据从表视图传递到另一个视图控制器

带有表格视图的视图仅适用于默认视图控制器