在获取数据期间索引超出部分中的行数范围
Posted
技术标签:
【中文标题】在获取数据期间索引超出部分中的行数范围【英文标题】:Index out of range in number of rows in section during fetching data 【发布时间】:2021-04-06 16:48:38 【问题描述】:何时尝试使用我的表格视图和进度条打开新控制器时出现“索引超出范围”。 我从 Firestore 数据库中获取数据,想法是当我点击“下一步”按钮时,我想更新进度条并使用新值重新加载表视图。行数必须等于组数,但每个练习的组数不同,所以我想动态更改行数。
class StartViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
var titleValue: String = ""
var dayOfWorkout: String = ""
var exerciseNumber = 0
var models: [DataCell2] = []
let user = Auth.auth().currentUser
var db = Firestore.firestore()
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var exerciseLabel: UILabel!
@IBOutlet weak var progressView: UIProgressView!
override func viewDidLoad()
super.viewDidLoad()
progressView.transform = progressView.transform.scaledBy(x: 1, y: 3)
tableView.delegate = self
tableView.dataSource = self
retrieveWorkouts()
@IBAction func nextButtonPressed(_ sender: UIButton)
nextExercise()
Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(updateUI), userInfo: nil, repeats: false)
tableView.reloadData()
@objc func updateUI()
progressView.progress = getProgress()
func getProgress() -> Float
return Float(exerciseNumber) / Float(models.count)
func nextExercise()
if exerciseNumber + 1 < models.count
exerciseNumber += 1
else
exerciseNumber = 0
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
**//HERE IS ERROR**
return models[exerciseNumber].sets!
以及从 Firestore 获取数据的方法
func retrieveWorkouts()
db.collection("users").document("\(user!.uid)").collection("WorkoutsName").document("\(titleValue)").collection("Exercises").order(by: "Number").getDocuments (querySnapshot, error) in
if let error = error
print("\(error.localizedDescription)")
else
if let snapshotDocuments = querySnapshot?.documents
for doc in snapshotDocuments
let data = doc.data()
if let numberDb = data["Number"] as? Int, let exerciseDb = data["Exercise"] as? String, let kgDb = data["kg"] as? Int, let setsDb = data["Sets"] as? Int, let repsDb = data["Reps"] as? Int, let workoutName = data["workoutName"] as? String
print("data is \(data)")
let newModel = DataCell2(Number: numberDb, Exercise: exerciseDb, kg: kgDb, sets: setsDb, reps: repsDb, workoutName: workoutName)
self.models.append(newModel)
self.tableView.reloadData()
【问题讨论】:
尝试在retrieveWorkouts
方法内的主线程上调用reloadData
。你确定nextExercise
里面的逻辑吗?我认为您在其中切换了 if 和 else 条件。
不幸的是,主线程内的 reloadData 不起作用
您仍然应该这样做。你确定nextExercise
方法吗?
是的,我确定。唯一不起作用的是检索部分函数中的集合数为行数。
这有点跑题了,但你不会想在 for 循环 for doc in snapshotDocuments
内一遍又一遍地重新加载你的 tableView。之后移动重新加载,因此它只需在填充数据源后执行一次。
【参考方案1】:
您有时间问题。视图将在加载时尝试创建 tableView。此时模型数组将为空,因为异步 firebase 方法不会运行并更新它。但是你将executiveNumber初始化为0。
这意味着 numberOfRowsInSection
委托方法将尝试访问 models[0
] 但由于此时数组为空,因此不存在并导致索引超出范围崩溃。
你可以通过一些防御性编程来解决这个问题:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
guard !model.isEmpty else return 0
return models[exerciseNumber].sets!
您还可以添加第二个守卫或前提条件以确保executiveNumber
【讨论】:
【参考方案2】:您基于行数
models[exerciseNumber].sets!
你正在设置锻炼号码
func nextExercise()
if exerciseNumber + 1 < models.count
exerciseNumber += 1
else
exerciseNumber = 0
但是,这里有一个逻辑错误:您正在检查练习数是否小于 models.count,如果是,则增加它。这将导致exerciseNumber == models.count,并且由于数组是零索引的,这将超出数组的末尾并给出超出范围的错误。
一个简单的解决方法是将方法更改为:
func nextExercise()
exerciseNumber += 1
if exerciseNumber == models.count
exerciseNumber = 0
return exerciseNumber
有更聪明的方法可以做到这一点,但现在可以。
【讨论】:
不幸的是它仍然不起作用。但是我怀疑我在 nextExercise 中的逻辑是否不好,因为我从exerciseNumber = 0 开始,如果exerciseNumber 大于models.count 我增加,但是当exerciseNumber 将等于models.count 我的exerciseNumber 将再次为0,所以我从头开始,这里有什么问题? 我很抱歉 - 我误读为if exercise < model.count
。在阅读然后剪切和粘贴时,我设法错过了+ 1
位。我的错!以上是关于在获取数据期间索引超出部分中的行数范围的主要内容,如果未能解决你的问题,请参考以下文章