【问题标题】:Collection Views in iOSiOS 中的集合视图
【发布时间】:2018-08-08 18:29:04
【问题描述】:

我试图使用 swift 4 和 openWeather API 构建一个天气应用程序,但我卡在了这个函数中:

func fetchWeather(){
    let weatherGetter = GetWeather()
    self.cityWeather = [Temperature]()
            for city in cities {
                    weatherGetter.getWeather(city: city) { (temp) in
                        guard let temp = temp else {return}
                        print(temp)
                        self.cityWeather?.append(temp)
                }
            }
    print(self.cityWeather?.count)
    self.collectionView?.reloadData()
}

所以这个函数在控制台中给了我这个

可选(0) 温度(城市:“伦敦”,cityTemperature:“294.06”,tempIcon:“01d”) 温度(城市:“东京”,cityTemperature:“297.33”,tempIcon:“09n”) 温度(城市:“巴黎”,cityTemperature:“298.0”,tempIcon:“01d”) 温度(城市:“莫斯科”,cityTemperature:“291.41”,tempIcon:“01n”)

这对我来说真的很奇怪,因为 print(self.cityWeather?.count) 是在 for 循环之后使用的,但在控制台中 Optional(0) 是第一位的。

所以如果我用这个方法

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return cityWeather?.count ?? 0
}

我的集合视图单元格不会显示,因为它返回 0。

但是如果在 self.cityWeather?.append(temp) 之后使用 print(self.cityWeather) 我明白了! (我删除了所有其他打印语句):

可选([WhatsWeather.Temperature(city: "Moscow", cityTemperature: "291.41", tempIcon: "01n")]) 可选([WhatsWeather.Temperature(城市:“莫斯科”,cityTemperature:“291.41”,tempIcon:“01n”),WhatsWeather.Temperature(城市:“伦敦”,cityTemperature:“294.05”,tempIcon:“01d”)]) 可选([WhatsWeather.Temperature(城市:“莫斯科”,cityTemperature:“291.41”,tempIcon:“01n”),WhatsWeather.Temperature(城市:“伦敦”,cityTemperature:“294.05”,tempIcon:“01d”),WhatsWeather .Temperature(城市:“巴黎”,cityTemperature:“298.0”,tempIcon:“01d”)]) 可选([WhatsWeather.Temperature(城市:“莫斯科”,cityTemperature:“291.41”,tempIcon:“01n”),WhatsWeather.Temperature(城市:“伦敦”,cityTemperature:“294.05”,tempIcon:“01d”),WhatsWeather .Temperature(city: "Paris", cityTemperature: "298.0", tempIcon: "01d"), WhatsWeather.Temperature(city: "Tokyo", cityTemperature: "297.38", tempIcon: "09n")])

【问题讨论】:

  • count 逻辑存在缺陷,请查看更新后的答案。
  • @rakesha-shastri 谢谢你的帮助!

标签: swift xcode dictionary uicollectionview


【解决方案1】:

只有在所有城市数据都存储在您的数据源中之后,您才应该重新加载collectionView,并且由于这是一个 API 调用,因此接收每个响应都需要一些时间。所以你应该做的是检查完成内部是否已收到所有数据,然后重新加载collectionView

func fetchWeather(){
    let weatherGetter = GetWeather()
    self.cityWeather = [Temperature]()
    var networkCallsDone = 0
    for city in cities {
        weatherGetter.getWeather(city: city) { (temp) in
            networkCallsDone += 1
            guard let temp = temp else {
                if networkCallsDone == cities.count {
                    DispatchQueue.main.async {
                        collectionView.reloadData()    //In case the last network call to finish does not return valid data
                    }        
                }
                return
            }
            print(temp)
            self.cityWeather?.append(temp)
            if networkCallsDone == cities.count {
                 DispatchQueue.main.async {
                     collectionView.reloadData()
                 }
            }
        }
    }
}

编辑:感谢 matt 在检查 count 和线程问题时指出逻辑错误。

【讨论】:

  • 您的想法看起来不错,但查看count 的技术是错误的。循环并且直到结束才重新加载的方法是使用 DispatchGroup。
  • DispatchQueur.main.async {self.collectionView?.reloadData()} 在 for 循环中对我很有用,只是城市的顺序以某种方式搞砸了
  • whoops 我没有注意到它会在后台线程中,因为它是一个网络调用。我的错。谢谢@matt。我理解计数的事情。你的意思是我错过了guard 的计数。我会解决这个问题并更新答案。再次感谢。
  • @matt 我已经更新了答案,我希望这就是你的意思。如果没有,请随时编辑当前答案或发布新答案。
【解决方案2】:

那是因为您在weatherGetter.getWeather 块中附加了cityWeather,这是异步操作并同步重新加载collectionView(在数据从服务器返回之前)。

试试这个:

func fetchWeather(){
    let weatherGetter = GetWeather()
    self.cityWeather = [Temperature]()
    for city in cities {
        weatherGetter.getWeather(city: city) { (temp) in
            guard let temp = temp else {return}
            self.cityWeather?.append(temp)
            self.collectionView?.reloadData()
        }
    }
}

【讨论】:

  • 每次收到城市数据时,您都在重新加载collectionView,我认为这不是 OP 想要的,也不是任何人想要的。在收到所有数据后,您只想这样做一次。
猜你喜欢
  • 2012-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
  • 2014-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多