UICollectionView不响应UISearchBar

时间:2018-10-02 20:13:17

标签: ios swift api uicollectionview uisearchbar

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

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

这是我当前的代码:

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



}

编辑:我也尝试过这个。我在“ filmTable =“行中收到错误消息“无法对类型为[[NSDictionary]]”的值下标为“字符串”的索引。

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({$0.filmTitle.range(of: searchBar.text!) != nil})
        filmsTable.reloadData()
    }
}

4 个答案:

答案 0 :(得分:3)

不确定在您的代码中哪里出现了问题。但是,我可以为您提供一些建议和您正在尝试做的工作示例。

  1. 如果您尝试使用数组填充collectionView,请始终将数组声明为空数组(以防万一,您需要将其声明为空),而不是可选数组。
  2. 如果您不需要布尔值,请不要使用它-在您的情况下,诚实地说就不需要搜索布尔值。
  3. 尽可能简化您的代码。在您的情况下,filter函数将为您提供一个过滤后的数组-因此,无需在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({($0["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")
    }
}

答案 1 :(得分:1)

你唯一需要做的就是:

searchController.obscuresBackgroundDuringPresentation = false

答案 2 :(得分:0)

尝试:

uart_frame frame

UISearchBarDelegate: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() } 而非(_ searchBar:...

答案 3 :(得分:0)

希望可以尝试一下:

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