我有一个获取位置坐标和获取天气数据的函数。此函数用于代码中的其他位置。
目前我正在cellForRowAt中直接使用urlsession,但不想重复代码。是否有方法在TableViewController的cellForRowAt中调用此天气函数来更新单元格?
class Data {
static func weather (_ coord:String, completion: @escaping...([String?]) -> (){
let url = URL(string: "https://")
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
let json = processData(data) //returns [String]?
completion(json)
}
task.resume()
}
static func processData(_ data: Data) -> [String]? {
}
}
在cellForRowAt中,在返回单元格之前,如何修改weather函数以获取此处的值,但是weather函数的原始功能taking completion也应该保留?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ...
Data.weather() ** ??? **
cell.label.text = "" // value from weather
return cell
}
最佳答案
在cellForRowAt indexPath
中触发网络呼叫是个坏主意。每当用户滚动表视图时,都会调用该方法。这可能会导致大量的网络呼叫。
相反,你应该:
只在需要时打电话。例如,您可以在viewWillAppear
中执行此操作。每次应用程序切换到tableView时都会调用此方法
将网络呼叫的结果存储在模型中。这可能是一个简单的array
。
用reloadData
重新绘制tableView
在cellForRowAt indexPath
中,使用array
中的数据配置单元格。
让我们看一个例子(它是不完整的,但应该给你一个想法,做什么):
class WeatherTableView: UITableView {
var weatherData: [String]
override func viewWillAppear(_ animated: Bool) {
loadWeatherData()
}
private func loadWeatherData() {
// I just set some data here directly. Replace this with your network call
weatherData = ["Here comes the sun", "Rainy with chance of meatballs", "It's raining cats and dogs"]
// Make sure the tableView is redrawn
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "weatherDataCell")
cell.label.text = weatherData[indexPath.row]
return cell
}
}