UICollectionView 不响应 UISearchBar

UICollectionView not responding to UISearchBar

我创建了一个包含来自 API 的数据的 UICollectionView,它显示标题和海报图像。 UICollection 可以正常显示两者。

我正在尝试实现一个基于标题进行搜索的 UISearchBar。我遇到的问题是 UICollectionView 在使用 UISearchBar 时没有响应或更新。

这是我当前的代码:

import UIKit
import AFNetworking

class FilmsViewController: UIViewController, UICollectionViewDelegate, 
UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, 
UISearchBarDelegate, UISearchControllerDelegate {

var films: [NSDictionary]?
var filteredFilms: [NSDictionary]?
var searching:Bool = false



override func viewDidLoad() {
    super.viewDidLoad()

    filmsTable.dataSource = self
    filmsTable.delegate = self

    loadFilms()

}

override func viewDidAppear(_ animated: Bool) {

    navigationItem.titleView = imageView
}

//SEARCH BAR

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {

    self.filteredFilms?.removeAll()
    if searchText != "" {
        searching = true
        for film in self.films! {
            if (film["title"] as! String).contains(searchText.lowercased()) {
                self.filteredFilms?.insert(film, at: (filteredFilms?.endIndex)!)
            }
        }
    } else {
        searching = false 
        self.filteredFilms = self.films
    }

    filmsTable.reloadData()
}

/*
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    let search = searchBar.text!

    if search.isEmpty {
        self.filmsTable.reloadData()
    }
    else {

        // let search = searchBar.text!

        filteredFilms = films!.filter({ (text) -> Bool in

            //Access the title and sectors
            let filmTitle = text["title"] as! NSString

            //Create a range for both
            let range1 = filmTitle.range(of: search, options: NSString.CompareOptions.caseInsensitive)

            self.filmsTable.reloadData()
            return range1 != nil

        })

        self.filmsTable.reloadData()

    }

}

*/

//Collection View Layout

func collectionView(_ _collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    if searching {
        return filteredFilms?.count ?? 0
    } else {
        return films?.count ?? 0
    }
}




    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = filmsTable.dequeueReusableCell(withReuseIdentifier: "filmCell", for: indexPath) as! FilmCell

        if searching {
            let film = filteredFilms![indexPath.row]
            let title = film["title"] as! String
            cell.titleLabel.text = title

        } else {
            let film = films![indexPath.row]
            let title = film["title"] as! String

            cell.titleLabel.text = title

        }

        return cell
    }

    //End Collection View Layout

    //Parse Film API

    func loadFilms() {

        let apiKey = ""
        let url = URL(string: "https://api.themoviedb.org/3/movie/now_playing?api_key=\(apiKey)&language=en-US&page=1")
        let request = URLRequest(
            url: url! as URL,
            cachePolicy: URLRequest.CachePolicy.reloadIgnoringLocalCacheData,
            timeoutInterval: 10 )

        let session = URLSession (
            configuration: URLSessionConfiguration.default,
            delegate: nil,
            delegateQueue: OperationQueue.main
        )

        let task = session.dataTask(with: request, completionHandler: { (dataOrNil, response, error) in
            if let data = dataOrNil {
                if let resposeDictionary = try! JSONSerialization.jsonObject(with: data, options:[]) as? NSDictionary {

                    self.films = resposeDictionary["results"] as? [NSDictionary]
                    print("response: \(resposeDictionary)")
                }

            }

            self.filteredFilms = self.films
            self.filmsTable.reloadData()

        })

        task.resume()

    }

    //End Parse Film API



}

编辑:我也试过这个。我收到错误 "Cannot subscript a value of type '[NSDictionary]' with an index of type 'String' at the "filmTable =" line.

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchBar.text == nil || searchBar.text ==  "" {
        searching = false
        filmsTable.reloadData()
    } else {
        searching = true
        let filmTitle = films!["title"] as! NSString
        filteredFilms = films!.filter({[=11=].filmTitle.range(of: searchBar.text!) != nil})
        filmsTable.reloadData()
    }
}

尝试:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    self.filteredFilms?.removeAll()
    if searchText != "" {
        searching = true
        for film in self.films! {
            if (film["title"] as! String).contains(searchText.lowercased()) {
                self.filteredFilms?.insert(film, at: (filteredFilms?.endIndex)!)
            }
        }
    } else {
        searching = false
        self.filteredFilms = self.films
    }

    filmsTable.reloadData()
}  

UISearchBarDelegate: (_ searchBar:... 不是 (searchBar:...

试试这个,希望它会起作用:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchBar.text == nil || searchBar.text ==  "" {
        searching = false
        filmsTable.reloadData()
    } else {
        searching = true
        filteredFilms = films.filter({[=10=].["title"].range(of: searchBar.text!) != nil})
        filmsTable.reloadData()
    }
}  

不确定您的代码中到底哪里出了问题。但是,我可以给你一些建议和一个你正在尝试做的工作的例子。

  1. 如果您尝试使用数组填充 collectionView,请始终将数组声明为空数组(以防您需要它为空)而不是可选数组。
  2. 如果您不需要布尔值,请不要使用它 - 在您的情况下,老实说不需要搜索布尔值。
  3. 尽可能简化您的代码。在您的情况下,过滤器功能将为您提供一个过滤后的数组 - 因此无需在 filteredFilms 数组中插入或附加项目。

这是您想要执行的工作示例:

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource, UISearchBarDelegate {

    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .white
        cv.dataSource = self
        cv.delegate = self
        return cv
    }()

    var films = [["title" : "one"], ["title" : "two"], ["title" : "three"]]
    var filteredFilms = [Dictionary<String, String>]()

    let searchBar = UISearchBar()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(searchBar)
        searchBar.translatesAutoresizingMaskIntoConstraints = false
        searchBar.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 60).isActive = true
        searchBar.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
        searchBar.heightAnchor.constraint(equalToConstant: 60).isActive = true
        searchBar.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true

        self.view.addSubview(collectionView)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.topAnchor.constraint(equalTo: self.searchBar.bottomAnchor).isActive = true
        collectionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
        collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        collectionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true

        collectionView.register(Cell.self, forCellWithReuseIdentifier: "cell")

        self.searchBar.delegate = self
        self.filteredFilms = films
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return filteredFilms.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 100, height: 100)
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchText == "" {
            self.filteredFilms = films
            self.collectionView.reloadData()
        } else {
            self.filteredFilms = films.filter({([=10=]["title"]?.contains(searchText.lowercased()))!})
            print(self.filteredFilms.count)
            self.collectionView.reloadData()
        }
    }

}

class Cell : UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    func setupViews() {
        self.backgroundColor = .red
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

您唯一需要做的是:

searchController.obscuresBackgroundDuringPresentation = false