UICollectionView 从另一个视图控制器返回时重复单元格

Posted

技术标签:

【中文标题】UICollectionView 从另一个视图控制器返回时重复单元格【英文标题】:UICollectionView duplicates cells when returning from another view controller 【发布时间】:2017-08-10 22:56:44 【问题描述】:

我一直在开发一个天气应用程序,并一直在使用 UICollectionView 来显示天气数据。

每当我打开另一个视图控制器并返回到 UICollectionView 的视图控制器时,我都会得到重复的单元格。

这里是代码。 我使用 Alamofire 发出 api 请求,将 json 结果附加到本地字符串,然后将其分配给单元格的文本标签。

    class VaanizhaiViewController: UICollectionViewController 


    // MARK: - flow layout

    let columns : CGFloat = 2.0
    let inset : CGFloat = 3.0
    let spacing : CGFloat = 3.0
    let lineSpacing : CGFloat = 3.0
    var isRandom : Bool = false

    // MARK: - Variables
    var apiKey: String = "55742b737e883a939913f2c90ee11ec0"
    var country : String = ""
    var zipCode : String = ""
    var json : JSON = JSON.null
    var cityNames: [String] = []
    var temperature: [Int] = []
    var weather: [String] = []

    // MARK: - Actions


    // MARK: - view did load
    override func viewDidLoad() 
        super.viewDidLoad()
        let layout = BouncyLayout()
        self.collectionView?.setCollectionViewLayout(layout, animated: true)
        self.collectionView?.reloadData()

    

    override func viewDidAppear(_ animated: Bool) 
        for i in 0...zip.count-1
            parseURL(zipCode: "\(zip[i])", country: "us")
        

    


    // MARK: - Functions

    func parseURL(zipCode: String, country: String)

        let url = "http://api.openweathermap.org/data/2.5/weather?zip=\(zipCode),\(country)&APPID=\(apiKey)&units=metric"
        requestWeatherData(link: url)
    

    func requestWeatherData(link: String)
        Alamofire.request(link).responseJSON response in
            if let value = response.result.value
                self.json = JSON(value)
                self.cityNames.append(self.json["name"].string!)
                let cTemp = ((self.json["main"]["temp"].double)!)
                self.temperature.append(Int(cTemp))
                let cWeather = self.json["weather"][0]["main"].string!
                self.weather.append(cWeather)
                self.collectionView?.reloadData()

            
        

    




    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int 

        return 1
    


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 

        return self.cityNames.count

    

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

        if !self.cityNames.isEmpty 


        cell.cityLabel.text = self.cityNames[indexPath.row]
        cell.tempLabel.text = String (self.temperature[indexPath.row])
        cell.weatherLabel.text = self.weather[indexPath.row]
            cell.backgroundColor = UIColor.brown
    

        return cell


   
// MARK: - UICollectionViewDelegateFlowLayout

extension VaanizhaiViewController: UICollectionViewDelegateFlowLayout
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
        let width = Int ((CGFloat(collectionView.frame.width) / columns) - (inset + spacing))
        return CGSize(width: width, height: width)
    

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets 
        return UIEdgeInsets(top: CGFloat(inset), left: CGFloat(inset), bottom: CGFloat(inset), right: CGFloat(inset))
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat 
        return spacing
    

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat 
        return lineSpacing
    

【问题讨论】:

【参考方案1】:

您的 viewDidAppear 将在您每次访问视图控制器时被调用,而您的 viewDidLoad 只会在创建时被调用一次。

因此,您可能应该将对 self.collectionView?.reloadData() 的调用切换到 viewDidAppear 并将对 parseURL 的调用切换到 viewDidLoad

如果您需要更新您的天气数据(例如,在刷新时),那么您需要重组您的 requestWeatherData 以停止附加到您的数组,并改为替换。

【讨论】:

以上是关于UICollectionView 从另一个视图控制器返回时重复单元格的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 显示空单元格

UICollectionView 和一个视图控制器中的其他视图

无法从另一个视图控制器获取表视图数据

从另一个导航控制器弹出视图控制器到另一个视图控制器

嵌入式视图控制器中的 UICollectionView 不会调用 cellForItemAtIndexPath

从另一个视图控制器更新视图控制器的内容而不打开它