UICollectionView 不响应 UISearchBar

问题描述 投票:0回答:4

我创建了一个

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



}

编辑:我也尝试过这个。我在

"filmTable =" line
:

处收到错误

“无法使用“String”类型的索引为“[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()
    }
}
ios swift uicollectionview uisearchbar
4个回答
3
投票

不确定您的代码中到底在哪里遇到了问题。但是,我可以给您一些建议和您正在尝试做的事情的可行示例。

  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({($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
投票

您唯一需要做的就是:

searchController.obscuresBackgroundDuringPresentation = false

0
投票

尝试:

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:...


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()
    }
}  
© www.soinside.com 2019 - 2024. All rights reserved.