Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
687 views
in Technique[技术] by (71.8m points)

swift - Select Filtered search results

Whenever I search in my app I get the correct results to display but when I tap on the cell I searched for it always plays the first index of the table before I do the search. I am trying to use my isSearching Bool in my didselectcell but cant seem to get it to work.

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()
        }
    }
}
}
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think that the issue is that you are tracking whether you are searching or not yourself and manipulating the source data array.

I have an example playground snippet I have used for some other answers which shows you how to do this more efficiently and has some handy helper functions to make it easier.


I think the key parts of this that would be beneficial to you are:

keep a seperate array just of search results, only used when search is active

var filteredNames = [String]()

Make sure that you adjust the count and rows used when searching or not

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
}

You can use the following helper functions to help you out.

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()
}

Full UISearchController Example (playground)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...