UICollectionView не отвечает на UISearchBar - PullRequest
0 голосов
/ 02 октября 2018

Я создал UICollectionView, содержащий данные из API, который отображает заголовки и изображения постеров.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



}

РЕДАКТИРОВАТЬ: Я также пробовал это.Я получаю сообщение об ошибке "Невозможно добавить значение типа '[NSDictionary]" с индексом типа "String" в строке "filmTable =".

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

Ответы [ 3 ]

0 голосов
/ 03 октября 2018

Попробуйте, надеюсь, это сработает:

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()
    }
}  
0 голосов
/ 03 октября 2018

Не уверен, где именно в вашем коде у вас проблемы.Тем не менее, я могу дать вам несколько советов и рабочий пример того, что вы пытаетесь сделать.

  1. Если вы пытаетесь заполнить collectionView с использованием массива, всегда объявляйте массивы как пустые (если вам это нужно), а не как опциональные.
  2. Если вы этого не сделаетенужен логический, не используйте его - в вашем случае поиск логического не нужен, если честно.
  3. максимально упростите ваш код.В вашем случае функция фильтра предоставит вам отфильтрованный массив - поэтому нет необходимости вставлять или добавлять элементы в массиве FilterFilms.

Вот рабочий пример того, что вы хотите сделать:

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")
    }
}
0 голосов
/ 03 октября 2018

try:

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:... not (searchBar:...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...