ios - 为什么在尝试重新加载数据时总是出现索引超出范围错误?
问题描述
我正在尝试从我的 Firebase 数据库中检索关于number
我的posts
集合中包含的“效果”数量的数据。我希望每次effectIsTapped
调用该函数时都更新此数据。然后,我希望数组更新。目前,我EffectsLabelArray
在添加数据之前从 , 中删除所有元素。但是,毫无疑问,这会在以下行产生“致命错误:索引超出范围”:
let effects = self.effectsLabelArray[indexPath.row]
下面我详细说明我的代码:
var titleArray: [String] = []
var usernameArray: [String] = []
var contentArray: [String] = []
var postedTimeArray: [Any] = []
var effectsLabelArray: [Int] = []
var profileImageArray: [String] = []
var postIDArray: [Int] = []
var followingList: [String] = []
var documents: [DocumentSnapshot] = []
let db = Firestore.firestore()
let currentUserID = Auth.auth().currentUser?.uid
// Find the UserIDs of people following
// Where Field for those UserIDs in "Posts"
override func viewDidLoad() {
super.viewDidLoad()
// getFollowingPosts()
configureTableView()
getFollowingPosts()
}
func getFollowingPosts() {
db.collection("iAmFollowing").document(currentUserID!).getDocument { (document, error) in
if error != nil {
print("ERROR")
} else {
if let document = document, document.exists {
let followedUID = document.get("uid") as? String
self.db.collection("posts").whereField("uid", isEqualTo: followedUID!).getDocuments { (documents, error) in
for documents in documents!.documents {
let title = documents.get("Title") as! String
let content = documents.get("Content") as! String
let username = documents.get("username") as! String
let postID = documents.get("postID")
let counter = documents.get("counter")
self.titleArray.append(title)
self.contentArray.append(content)
self.usernameArray.append(username)
self.postIDArray.append(postID as! Int)
self.effectsLabelArray.append(counter as! Int)
print(self.titleArray)
self.tableView.reloadData()
}
}
}
}
}
}
func configureTableView() {
tableView.delegate = self
tableView.dataSource = self
// remove separators for empty cells
tableView.tableFooterView = UIView()
// remove separators from cells
tableView.separatorStyle = .none
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
titleArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
db.collection("iAmFollowing").document(currentUserID!).getDocument { (document, error) in
if let document = document, document.exists {
let followedUID = document.get("uid") as! String
self.db.collection("posts").whereField("uid", isEqualTo: followedUID).getDocuments { (documents, error) in
for documents in documents!.documents {
let counter = documents.get("counter") as! Int
self.effectsLabelArray.append(counter)
let postID = self.postIDArray[indexPath.row]
let title = self.titleArray[indexPath.row]
let content = self.contentArray[indexPath.row]
let username = self.usernameArray[indexPath.row]
let effects = self.effectsLabelArray[indexPath.row]
cell.titleLabel.text = title
cell.contentLabel.text = content
cell.usernameLabel.text = username
cell.postIDLabel.text = String(postID)
cell.effectsLabel.text = String(effects)
}
}
//Get effects
//Append Effects
//Set title to indexPath.row
//Set them to cell label
}
}
return cell
}
@IBAction func effectsButtonIsTapped(_ sender: Any) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.effectsLabelArray.removeAll()
self.tableView.reloadData()
}
}
// Do any additional setup after loading the view.
@IBAction func removeEffectIsTapped(_ sender: Any) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.effectsLabelArray.removeAll()
self.tableView.reloadData()
}
}
@IBAction func logoutIsTapped(_ sender: Any) {
try! Auth.auth().signOut()
let loginDialogueViewController = storyboard?.instantiateViewController(withIdentifier: "LoginDialogueViewController")
let navigationController = UINavigationController(rootViewController: loginDialogueViewController!)
let share = UIApplication.shared.delegate as? AppDelegate
share?.window?.rootViewController = navigationController
share?.window?.makeKeyAndVisible()
navigationController.modalPresentationStyle = .fullScreen
present(navigationController, animated: false)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
}
*/
}
如果有人可以为我回答这个问题,我将不胜感激。
解决方案
首先,尽量不要调用reloadData()
循环。这可能会导致不必要的副作用。尝试在查询数据库时将所有内容添加到数组中,在所有数据都在数组中之后,然后才调用reloadData()
. 因为它将使 中的所有内容无效UITableView
并重新加载所有必要的数据和单元格。
显示单元格时也是如此tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
。仅在从数据库中获取所有内容后设置单元格的属性,不要重复访问 UI 级别。这可能会导致故障和您的应用在一段时间内无响应。随着数据的增长,将呈指数增长。
然后,effectsLabelArray
在其他地方也进行了编辑,那么您永远无法确定该数组的计数或大小。而不是通过self.effectsLabelArray[indexPath.row]
尝试使用self.effectsLabelArray[safe: index.row]
. 然后,当预期值不存在时,您可以添加额外的处理。
推荐阅读
- python - Adding to a dictionary inside the for loop - incomprehensible behaviour
- ios - Setting a shared title within a common Header View amongst Views; per Active View
- python - how am ı use python websocket
- r - How to plot raw data and add predict + confidence intervals using maximum likelihood function in R gpplot2?
- google-apps-script - 如何使用新编辑器部署新版本的谷歌应用程序网络应用程序
- python - 保存外键对象 django 表单
- python - 使用多个构造函数和 **kwargs 进行子类化
- python - VS Code:QT 无法连接显示
- kubernetes - kubernetes 部署将秘密挂载为文件夹而不是文件
- angular - Angular 11 和 Zuul Gateway 出现热重载问题