gpt4 book ai didi

ios - UITableView 索引超出范围

转载 作者:行者123 更新时间:2023-11-30 11:56:44 27 4
gpt4 key购买 nike

我遇到了选项卡应用程序崩溃的问题,而且我真的找不到解决方案。当应用程序首次执行并且当我选择第三个选项卡项(天气预报)时,一切正常,表数据正在加载其中的所有数据,并且一切都显示正常,用户可以毫无问题地进行交互。当我选择另一个选项卡项目然后返回天气预报选项卡时,会发生崩溃问题。我担心的是,有时它会崩溃,但有时不会。这是我真正无法理解的,为什么它会连续工作一次甚至几次,有时它会在第一次尝试时崩溃。我想在某个时候当 viewdidAppear 加载时, View 生命周期中,我的数组没有及时填充,因此 TableView 试图访问不存在的数组元素并崩溃。这就是我尝试使用线程和调度队列来管理的内容,但仍然出现问题..

有什么想法吗?非常感谢您的帮助。

有时我会收到此错误消息:

2017-12-09 14:19:11.431048+0100 Le Baluchon[19344:5162393] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (0) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out)

但很多时候,我会在 VC 的第 73 行旁边看到此错误消息:

Thread 1: Fatal error: Index out of range

有什么想法吗?

这是我的 VIewController:

class WeatherViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet weak var weatherView: UITableView!
@IBOutlet weak var weatherDataLoading: UIActivityIndicatorView!

let error = Notification.Name(rawValue: "Error")
var selectedRow: Int?
var count: Int = 0
var names = [String]()
var temps = [String]()
var dates = [String]()
var climates = [String]()
var forecastDates = [String]()
var forecastClimates = [String]()

override func viewDidLoad() {
super.viewDidLoad()

self.weatherView.dataSource = self
self.weatherView.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(displayErrorAlert), name: error, object: nil)
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

WeatherRequest.getWeatherCast(completion: { (names, temps, dates, climates, forecastdates, forecastclimates) in
self.names = names
self.temps = temps
self.dates = dates
self.climates = climates
self.forecastDates = forecastdates
self.forecastClimates = forecastclimates
self.weatherView.reloadData()
self.weatherDataLoading.isHidden = true
})
}

@objc func displayErrorAlert() {

let alertVC = UIAlertController(title: "Error", message: "Couldn't retrieve data from servor", preferredStyle: .alert)
alertVC.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alertVC, animated: true, completion: nil)

}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCell(withIdentifier: "table_cell", for: indexPath) as! WeatherViewCell

cell.separatorInset = UIEdgeInsets.zero

cell.firstStackView.constant = tableView.frame.height / 4
cell.cityName.text = names[indexPath.item]
cell.cityDate.text = dates[indexPath.item]
cell.cityClimate.text = climates[indexPath.item]
cell.cityTemp.text = temps[indexPath.item]

cell.firstForecastedClimate.text = forecastClimates[count]
cell.firstForecastedDate.text = forecastDates[count]
count += 1
cell.secondForecastedClimate.text = forecastClimates[count]
cell.secondForecastedDate.text = forecastDates[count]
count += 1
cell.thirdForecastedClimate.text = forecastClimates[count]
cell.thirdForecastedDate.text = forecastDates[count]
cell.isExpanded = false

count += 8

return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

guard let cell = tableView.cellForRow(at: indexPath) as? WeatherViewCell
else { return }

selectedRow = indexPath.item

cell.contentView.backgroundColor = UIColor.darkGray
cell.contentView.alpha = 0.5

cell.isExpanded = !cell.isExpanded

self.weatherView.beginUpdates()
self.weatherView.endUpdates()
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {

guard let cell = tableView.cellForRow(at: indexPath) as? WeatherViewCell
else { return }

self.weatherView.beginUpdates()
cell.contentView.backgroundColor = nil
cell.contentView.alpha = 1
cell.isExpanded = false
self.weatherView.endUpdates()
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)

guard let selectedRow = selectedRow else { return }
guard let cell = weatherView.cellForRow(at: [0,selectedRow]) as? WeatherViewCell
else { return }
cell.isExpanded = false
weatherView.beginUpdates()
cell.contentView.backgroundColor = nil
cell.contentView.alpha = 1
weatherView.endUpdates()
clear()
}

func clear() {
count = 0
names = [String]()
temps = [String]()
dates = [String]()
climates = [String]()
forecastDates = [String]()
forecastClimates = [String]()
}
}

这是我从 API Yahoo Weather 获取数据的类。

class WeatherRequest {

static func getWeatherCast(completion: @escaping ([String], [String], [String], [String], [String], [String]) -> ()) {

DispatchQueue.global(qos: .userInteractive).async {

var names = [String]()
var temps = [String]()
var dates = [String]()
var climates = [String]()

var forecastDates = [String]()
var forecastClimates = [String]()

let url = URL(string: "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%20in(%22Miami%22%2C%20%22new%20york%22%2C%20%22chicago%22%2C%20%22philadelphia%22))%20and%20u%3D'c'&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")

let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in

guard let myData = data else { return }

do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let root = try decoder.decode(Root.self, from: myData)
for channel in root.channels {
dates.append(channel.item.condition.date)
temps.append(channel.item.condition.temp + " °C")
climates.append(channel.item.condition.text)
}

for channel in root.channels {
for forecast in channel.item.forecast {
forecastDates.append(forecast.date)
forecastClimates.append(forecast.text)
}
}
names = ["Miami", "New York", "Chicago", "Philadelphia"]
DispatchQueue.main.async {
completion(names, temps, dates, climates, forecastDates, forecastClimates)
}

} catch let fetchError {
print(fetchError)
}
}
task.resume()
}
}
}

最佳答案

该错误清楚地解释了这一点。当调用开始更新和结束更新时,将像这样检查行数。更新后的行数应等于更新前的行数加上或减去添加或删除的行数。在您的情况下,api 返回 4 个值,但当您更改选项卡并返回时,计数更改为 0(此处 api 响应延迟)。因此,在更新 4 之前和更新 0 之后,不会调用删除单元格。有关更多信息,请阅读 beginupdates 的描述,它有明确的记录。

关于ios - UITableView 索引超出范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47729801/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com