UICollectionViewCell 在刷新 swift 3 时失去价值

Posted

技术标签:

【中文标题】UICollectionViewCell 在刷新 swift 3 时失去价值【英文标题】:UICollectionViewCell loses value on refresh swift 3 【发布时间】:2017-04-18 08:50:26 【问题描述】:

第一张图片显示,每当我单击 collectionview 上的单元格时,它都会在 View Controller 的标题视图上显示所选单元格的 ID: 现在我的问题是,每当我对集合视图的标题进行排序并单击一个单元格时,ID 就消失了:

我现在不知道该怎么办,因为我找不到有关此的相关帖子。这是我的代码:

import UIKit

private let reuseIdentifier = "Cell"

class MovieCollectionViewController: UICollectionViewController 

    private let leftAndRightPadding: CGFloat = 24.0
    private let numberItemsPerRow: CGFloat = 2.0
    private let heightAdustment: CGFloat = 90.0

    var movies: [MOVIE]?
    var filteredMovies: [MOVIE]?

    var searchControllerMovie: UISearchController!


    func filterContentForSearchTextMovie(searchText: String) 
        filteredMovies = movies?.filter
            movie in
            return (movie.movTitle?.lowercased().contains(searchText.lowercased()))!
        
        collectionView?.reloadData()
    

    override func viewDidLoad() 
        super.viewDidLoad()

        self.searchControllerMovie = UISearchController(searchResultsController:  nil)
        self.searchControllerMovie.searchResultsUpdater = self
        self.searchControllerMovie.searchBar.text = ""
        self.searchControllerMovie.hidesNavigationBarDuringPresentation = false
        self.searchControllerMovie.dimsBackgroundDuringPresentation = true
        self.searchControllerMovie.obscuresBackgroundDuringPresentation = false

        searchControllerMovie.searchBar.becomeFirstResponder()
        self.navigationItem.titleView = searchControllerMovie.searchBar


        //SPACING BETWEEN COLLECTION VIEW CELLS
        let width = (collectionView!.frame.width - leftAndRightPadding) / numberItemsPerRow
        let layout = collectionViewLayout as! UICollectionViewFlowLayout
        layout.itemSize = CGSize(width: width, height: width + heightAdustment)

        //LOADER
        let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
        let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
        loadingIndicator.startAnimating();

        alert.view.addSubview(loadingIndicator)
        present(alert, animated: true, completion: nil)

        self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

        fetchMovie()
        // Do any additional setup after loading the view.

        setupNavBarButtons()
    

    func setupNavBarButtons() 
        let sortAsc = UIBarButtonItem(image: UIImage(named: "arrow_up")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(sortMovieByAsc))

        let sortDesc = UIBarButtonItem(image: UIImage(named: "arrow_down")?.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(sortMovieByDesc))
        navigationItem.rightBarButtonItems = [sortDesc, sortAsc]
    

    func sortMovieByAsc() 

        let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)

        let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
        loadingIndicator.startAnimating();

        alert.view.addSubview(loadingIndicator)
        present(alert, animated: true, completion: nil)

        let queryItems = [NSURLQueryItem(name: "sortQuery", value: "Title Ascending" )]
        let urlComps = NSURLComponents(string: "http://192.168.81.118:8080/mobileweb/android/getSortMovie")!
        urlComps.queryItems = queryItems as [URLQueryItem]?
        let URL = urlComps.url!
        URLSession.shared.dataTask(with: URL, completionHandler: (data, response, error) -> Void in

            if error != nil 
                print(error!)
                return
            

            do 

                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)

                self.movies = [MOVIE]()
                for dictionary in json as! [[String: AnyObject]] 

                    let movie = MOVIE()
                    movie.movTitle = dictionary["TITLE"] as? String
                    movie.movImage = dictionary["PHOTO_DIR"] as? String
                    self.movies?.append(movie)
                

                DispatchQueue.main.async 
                    self.dismiss(animated: false, completion: nil)
                    self.collectionView?.reloadData()
                

             catch let jsonError 
                print(jsonError)
            

        ).resume()

    

    func sortMovieByDesc() 
        let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)

        let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
        loadingIndicator.startAnimating();

        alert.view.addSubview(loadingIndicator)
        present(alert, animated: true, completion: nil)

        let queryItems = [NSURLQueryItem(name: "sortQuery", value: "Title Descending" )]
        let urlComps = NSURLComponents(string: "http://192.168.81.118:8080/mobileweb/Android/getSortMovie")!
        urlComps.queryItems = queryItems as [URLQueryItem]?
        let URL = urlComps.url!
        URLSession.shared.dataTask(with: URL, completionHandler: (data, response, error) -> Void in

            if error != nil 
                print(error!)
                return
            

            do 

                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)

                self.movies = [MOVIE]()
                for dictionary in json as! [[String: AnyObject]] 

                    let movie = MOVIE()
                    movie.movTitle = dictionary["TITLE"] as? String
                    movie.movImage = dictionary["PHOTO_DIR"] as? String
                    self.movies?.append(movie)
                

                DispatchQueue.main.async 
                    self.dismiss(animated: false, completion: nil)
                    self.collectionView?.reloadData()
                

                self.collectionView?.reloadData()

             catch let jsonError 
                print(jsonError)
            

        ).resume()

    


    func fetchMovie() 
        let url = URL(string: "http://192.168.81.118:8080/mobileweb/Android/getMovie")

        URLSession.shared.dataTask(with: url!, completionHandler: (data, response, error) -> Void in

            if error != nil 
                print(error!)
                return
            

            do 

                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers)

                self.movies = [MOVIE]()
                for dictionary in json as! [[String: AnyObject]] 

                    let movie = MOVIE()
                    movie.movTitle = dictionary["TITLE"] as? String
                    movie.movImage = dictionary["PHOTO_DIR"] as? String
                    movie.movID = dictionary["ID"] as? String
                    self.movies?.append(movie)
                

                DispatchQueue.main.async 
                    self.dismiss(animated: false, completion: nil)
                    self.collectionView?.reloadData()
                

             catch let jsonError 
                print(jsonError)
            


        ).resume()

    

    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    
    */

    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int 
        // #warning Incomplete implementation, return the number of sections
        return 1
    


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        if searchControllerMovie.isActive && searchControllerMovie.searchBar.text != "" 
            return (filteredMovies?.count)!
        
        // #warning Incomplete implementation, return the number of items
        return movies?.count ?? 0
    

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cellIdentifier = "MovieCollectionViewCell"
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as? MovieCollectionViewCell

        if searchControllerMovie.isActive && searchControllerMovie.searchBar.text != "" 
            cell?.movie = filteredMovies?[indexPath.row]
         else 
        // Configure the cell
            cell?.movie = movies?[indexPath.row]
        
        return cell!
    

    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
        print("Row:\(indexPath.row)")
//        let cell = collectionView.cellForItem(at: indexPath);
//        self.performSegue(withIdentifier: "showDetail", sender: cell)
    


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        if let indexPath = self.collectionView?.indexPath(for: sender as! UICollectionViewCell) 
            let movieDetail: MOVIE

            if searchControllerMovie.isActive && searchControllerMovie.searchBar.text != "" 
                movieDetail = (filteredMovies?[indexPath.item])!
            
            else 
                movieDetail = (movies?[indexPath.row])!
            
            let controller = segue.destination as! MovieDetailsViewController
            controller.movieDetail = movieDetail

        

    


extension MovieCollectionViewController: UISearchResultsUpdating 
    func updateSearchResults(for searchController: UISearchController) 
        filterContentForSearchTextMovie(searchText: searchController.searchBar.text!)
    

【问题讨论】:

1. i.stack.imgur.com/EJ2Se.png2.i.stack.imgur.com/FRIsV.png 当您在此处打印movieDetail 时,movieDetail 始终是正确的MOVIE 对象:controller.movi​​eDetail = movieDetail。 ? 我没有明白你的意思,先生@rett 【参考方案1】:

你需要添加这一行,过滤数据时忘记添加这一行..

 func sortMovieByDesc()
   for dictionary in json as! [[String: AnyObject]] 

                    let movie = MOVIE()
                    movie.movTitle = dictionary["TITLE"] as? String
                    movie.movImage = dictionary["PHOTO_DIR"] as? String
                    movie.movID = dictionary["ID"] as? String // this line

                    self.movies?.append(movie)
                


func sortMovieByAsc()
for dictionary in json as! [[String: AnyObject]] 

                    let movie = MOVIE()
                    movie.movTitle = dictionary["TITLE"] as? String
                    movie.movImage = dictionary["PHOTO_DIR"] as? String
                    movie.movID = dictionary["ID"] as? String // this line

                    self.movies?.append(movie)
                

 

【讨论】:

我是这里的新手,所以现在(我需要获得 15 个声望),以便我可以为您的评论点赞。对不起【参考方案2】:

collectionViews 不使用 indexPath.row,它们使用 indexPath.item。

改变

movieDetail = (movies?[indexPath.row])!

收件人

movieDetail = (movies?[indexPath.item])!

【讨论】:

我已经将其更改为(项目),但当我对集合视图进行排序时,我无法获取所选单元格的值

以上是关于UICollectionViewCell 在刷新 swift 3 时失去价值的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionViewCell 在刷新 swift 3 时失去价值

iOS bug记录UICollectionviewCell刷新变得这么莫名其妙?

使用 reloadItemsAtIndexPaths 重新加载 UICollectionViewCell 的 footerView

UICollectionView 的单元格在滚动后并不总是刷新

UICollectionView 刷新数据耗时较长

在 UICollectionViewCell 中添加模糊