首页 > 解决方案 > 为什么在尝试重新加载数据时总是出现索引超出范围错误?

问题描述

我正在尝试从我的 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?) {
    
}
*/

}

如果有人可以为我回答这个问题,我将不胜感激。

标签: iosswiftgoogle-cloud-firestore

解决方案


首先,尽量不要调用reloadData()循环。这可能会导致不必要的副作用。尝试在查询数据库时将所有内容添加到数组中,在所有数据都在数组中之后,然后才调用reloadData(). 因为它将使 中的所有内容无效UITableView并重新加载所有必要的数据和单元格。

显示单元格时也是如此tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell。仅在从数据库中获取所有内容后设置单元格的属性,不要重复访问 UI 级别。这可能会导致故障和您的应用在一段时间内无响应。随着数据的增长,将呈指数增长。

然后,effectsLabelArray在其他地方也进行了编辑,那么您永远无法确定该数组的计数或大小。而不是通过self.effectsLabelArray[indexPath.row]尝试使用self.effectsLabelArray[safe: index.row]. 然后,当预期值不存在时,您可以添加额外的处理。


推荐阅读