选择过滤的搜索结果

Posted

技术标签:

【中文标题】选择过滤的搜索结果【英文标题】:Select Filtered search results 【发布时间】:2018-11-02 13:05:33 【问题描述】:

每当我在我的应用程序中搜索时,我都会显示正确的结果,但是当我点击我搜索的单元格时,它总是在我进行搜索之前播放表格的第一个索引。我正在尝试在我的 didselectcell 中使用我的 isSearching Bool,但似乎无法让它工作。

import UIKit
import AVFoundation
import AVKit

class FordFlixViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate 

    let avPlayerViewController = AVPlayerViewController()

    var player: AVPlayer!

    var flix = [Courses]()
    var currentArray = [Courses]()

    let urlString = "http://homevideosdata.192.168.1.19.xip.io/getMoreClasses.php"

    @IBOutlet weak var searchBar: UISearchBar!

    @IBOutlet weak var homeVidsBtn: UIButton!

    @IBOutlet weak var grrr: UITableView!

    var isSearching = false

    lazy var refreshControl: UIRefreshControl = 
        let refreshControl = UIRefreshControl()
        refreshControl.tintColor = .black
        refreshControl.addTarget(self, action: #selector(requestData), for: .valueChanged)

        return refreshControl
    ()
    override func viewDidLoad() 
        super.viewDidLoad()
        setUpSearchBar()
        requestData()

        // Do any additional setup after loading the view.
    

    private func setUpSearchBar() 

        searchBar.showsScopeBar = true
        searchBar.selectedScopeButtonIndex = 0

        searchBar.delegate = self

        self.grrr.tableHeaderView = searchBar

        currentArray = flix
    
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
        guard !searchText.isEmpty else 
            isSearching = true
            currentArray = flix
            grrr.reloadData()
            return
        
        currentArray = flix.filter( video -> Bool in
            video.title.contains(searchText)
        )
        grrr.reloadData()
    
    func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) 


    
    let searchController = UISearchController(searchResultsController: nil)

    @objc func requestData() 
        print("requesting data")
        fetchJSON()
        let deadline = DispatchTime.now() + .microseconds(700)
        DispatchQueue.main.asyncAfter(deadline: deadline) 
            self.refreshControl.endRefreshing()
        
    
    func fetchJSON() 

        guard let url = URL(string: urlString) else  return 
        URLSession.shared.dataTask(with: url)  (data, response, err) in
            DispatchQueue.main.async 
                if let err = err 
                    print("Failed to get data from URL:", err)
                    return
                 else 
                    print("Loaded URL")
                

                guard let data = data else  return 

                do 
                    let decoder = JSONDecoder()
                    self.flix = try decoder.decode([Courses].self, from: data)
                    self.grrr.reloadData()
                    print(self.flix)
                 catch let jsonErr 
                    print("Failed to decode JSON", jsonErr)
                
            

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FlixTableViewCell

        let sweet = currentArray[indexPath.row]

        let bgColorView = UIView()
        bgColorView.backgroundColor = UIColor.black
        cell.selectedBackgroundView = bgColorView

        cell.titleLbl.text = sweet.title

        if let profileImageUrl = sweet.image 
            let url = URL(string: profileImageUrl)
            URLSession.shared.dataTask(with: url!, completionHandler:  (data, response, error) in
                if error != nil 
                    print(error)
                    return
                
                DispatchQueue.main.async 
                    cell.productImage.image = UIImage(data: data!)

                
            ).resume()
        
        return cell
    

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        if isSearching == false 
        let selectedCell = flix[indexPath.row].location

        let url = selectedCell

        // Create an AVPlayer, passing it the HTTP Live Streaming URL.
        let player = AVPlayer(url: URL(string: url)!)


        // Create a new AVPlayerViewController and pass it a reference to the player.
        let controller = AVPlayerViewController()
        controller.player = player

        // Modally present the player and call the player's play() method when complete.
        present(controller, animated: true) 
            player.play()

            
         else 
            if isSearching == true 
            let selectedCellTwo = currentArray[indexPath.row].location

            let url = selectedCellTwo

            // Create an AVPlayer, passing it the HTTP Live Streaming URL.
            let playerTwo = AVPlayer(url: URL(string: url)!)


            // Create a new AVPlayerViewController and pass it a reference to the player.
            let controller = AVPlayerViewController()
            controller.player = playerTwo

            // Modally present the player and call the player's play() method when complete.
            present(controller, animated: true) 
                playerTwo.play()
        
    



【问题讨论】:

请删除所有与您的问题相关的代码。请阅读minimal reproducible example 【参考方案1】:

我认为问题在于您是否在跟踪自己是否在搜索并操作源数据数组。

我有一个示例游乐场 sn-p 我已用于其他一些答案,它向您展示了如何更有效地做到这一点,并有一些方便的辅助功能使其更容易。


我认为对您有益的关键部分是:

只保留一个单独的搜索结果数组,仅在搜索处于活动状态时使用

var filteredNames = [String]()

确保调整搜索时使用的计数和行数

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    if isFiltering() 
        return filteredNames.count
     else 
        return names.count
    


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = UITableViewCell() // don't do this, i am for example.

    var name: String
    if isFiltering() 
        name = filteredNames[indexPath.row]
     else 
        name = names[indexPath.row]
    

    cell.textLabel?.text = name
    return cell

您可以使用以下辅助函数来帮助您。

func searchBarIsEmpty() -> Bool 
    // Returns true if the text is empty or nil
    return searchController.searchBar.text?.isEmpty ?? true


func isFiltering() -> Bool 
    return searchController.isActive && !searchBarIsEmpty()


完整的 UISearchController 示例(游乐场)

import UIKit
import PlaygroundSupport

class ViewController: UITableViewController 

    let searchController = UISearchController(searchResultsController: nil)

    var names = [
        "John",
        "Terry",
        "Martin",
        "Steven",
        "Michael",
        "Thomas",
        "Jason",
        "Matthew"
    ]
    var filteredNames = [String]()

    override func viewDidLoad() 
        super.viewDidLoad()

        self.title = "Search Example"

        searchController.searchResultsUpdater = self
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "Search"
        navigationItem.searchController = searchController
        definesPresentationContext = true
    

    override func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        if isFiltering() 
            return filteredNames.count
         else 
            return names.count
        
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = UITableViewCell() // don't do this, i am for example.

        var name: String
        if isFiltering() 
            name = filteredNames[indexPath.row]
         else 
            name = names[indexPath.row]
        

        cell.textLabel?.text = name
        return cell
    

    func searchBarIsEmpty() -> Bool 
        // Returns true if the text is empty or nil
        return searchController.searchBar.text?.isEmpty ?? true
    

    func isFiltering() -> Bool 
        return searchController.isActive && !searchBarIsEmpty()
    

    func filterContentForSearchText(_ searchText: String, scope: String = "All") 
        filteredNames = names.filter(( name : String) -> Bool in
            return name.lowercased().contains(searchText.lowercased())
        )

        tableView.reloadData()
    


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


let vc = ViewController()
let nav = UINavigationController()
nav.viewControllers = [vc]

PlaygroundPage.current.liveView = nav

【讨论】:

以上是关于选择过滤的搜索结果的主要内容,如果未能解决你的问题,请参考以下文章

在子选择中过滤 jsonb 结果

html 使用CSS选择器进行全文搜索以过滤结果

jQuery-编辑选择结果(添加筛选过滤或检测)

jquery过滤器搜索应根据文本选择匹配的DIV

如何根据用户提供的过滤值显示搜索结果?

基于 HTML 5 Geo Location 按表单选择下拉列表过滤结果