使用搜索栏过滤图像数据

人气:745 发布:2022-10-16 标签: filtering swift uisearchbar uisearchbardelegate

问题描述

我正在尝试过滤API中的数据。已成功加载到具有表格视图单元格的视图控制器中。这是一个电影应用程序。我正在尝试根据用户在文本框中键入的内容来筛选数据。我在代码筛选器中提到了电影的标题,但代码只能筛选电影的标题和概述,但图像字段保持未筛选状态,如图像、概述等。这是结构模型。

import Foundation

struct Movie: Decodable {
    let originalTitle: String
    let overview: String
    let posterPath: String
    
    enum CodingKeys: String, CodingKey {
        case originalTitle = "original_title"
        case overview
        case posterPath = "poster_path"
    }
    
} 

以下是协议类代码。

import Foundation

class MoviePresenter: MoviePresenterProtocol {
    
    private let view: MovieViewProtocol
    private let networkManager: NetworkManager
    var movies = [Movie]()
    private var cache = [Int: Data]()
    var rows: Int {
        return movies.count
    }
    
    init(view: MovieViewProtocol, networkManager: NetworkManager = NetworkManager()) {
        self.view = view
        self.networkManager = networkManager
    }
    
    
    func getMovies() {
        let url = "https://api.themoviedb.org/3/movie/popular?language=en-US&page=3&api_key=6622998c4ceac172a976a1136b204df4"
        
        networkManager.getMovies(from: url) { [weak self] result in
            switch result {
            case .success(let response):
                self?.movies = response.results
                self?.downloadImages()
                DispatchQueue.main.async {
                    self?.view.resfreshTableView()
                }
            case .failure(let error):
                
                DispatchQueue.main.async {
                    self?.view.displayError(error.localizedDescription)
                }
            }
        }
    }
    
    func getTitle(by row: Int) -> String? {
        return movies[row].originalTitle
    }
    
    func getOverview(by row: Int) -> String? {
        return movies[row].overview
    }
    
    func getImageData(by row: Int) -> Data? {
        return cache[row]
    }
    
   
    
    private func downloadImages() {
        let baseImageURL = "https://image.tmdb.org/t/p/w500"
        let posterArray = movies.map { "(baseImageURL)($0.posterPath)" }
        
        let group = DispatchGroup()
        group.enter()
        for (index, url) in posterArray.enumerated() {
            networkManager.getImageData(from: url) { [weak self] data in
                if let data = data {
                    self?.cache[index] = data
                }
            }
        }
        group.leave()
        group.notify(queue: .main) { [weak self] in
            self?.view.resfreshTableView()
        }
    }
    
    
}

以下是控制器代码。

import UIKit

class MovieViewController: UIViewController, UISearchBarDelegate {
    
    
    @IBOutlet weak var userName: UILabel!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var searchBar: UISearchBar!
    
    private var presenter: MoviePresenter!
    
    var finalname = ""
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

       userName.text = "Hello: " + finalname
       setUpUI()
       presenter = MoviePresenter(view: self)
       searchBarText()
       
    }
    private func setUpUI() {
        tableView.dataSource = self
        tableView.delegate = self
    }
    
    
   private func searchBarText() {
        searchBar.delegate = self
    }
    
    @IBAction func selectSegment(_ sender: UISegmentedControl) {
        
        if sender.selectedSegmentIndex == 1{
         setUpUI()
        presenter = MoviePresenter(view: self)
        presenter.getMovies()
        }
    }
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchText == ""{
            presenter.getMovies()
        }
        else {
            presenter.movies =  presenter.movies.filter({ movies  in
                return movies.originalTitle.lowercased().contains(searchText.lowercased())
               
            })
        }
        
        tableView.reloadData()
    }
   
    
}

extension MovieViewController: MovieViewProtocol {
    
    func resfreshTableView() {
        tableView.reloadData()
    }
    
    func displayError(_ message: String) {
        let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
        let doneButton = UIAlertAction(title: "Done", style: .default, handler: nil)
        alert.addAction(doneButton)
        present(alert, animated: true, completion: nil)
    }
    
}

extension MovieViewController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        presenter.rows
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell
        
        let row = indexPath.row
        let title = presenter.getTitle(by: row)
        let overview = presenter.getOverview(by: row)
        let data = presenter.getImageData(by: row)
        cell.configureCell(title: title, overview: overview, data: data)
        return cell
    }
    
   func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController
        
        let row = indexPath.row
       dc.titlemovie = presenter.getTitle(by: row) ?? ""
       dc.overview = presenter.getOverview(by: row) ?? ""
       dc.imagemovie = UIImage(data: presenter.getImageData(by: row)!)
        self.navigationController?.pushViewController(dc, animated: true)
   }
    
    
}


extension MovieViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
}

这是结果的屏幕截图。

推荐答案

在Tableview中缓存图片有一点棘手,当单元格发生变化或自身重用时可能会出现问题 这是因为当文本不同时,您会看到相同的图像。

有两个著名的包,你可以使用它来解决你的问题,而且它很容易使用,有很多选项。

1-Kingfisher

2-SDWebImage

324