修复致命错误:数组索引超出范围

时间:2019-06-10 15:24:49

标签: arrays swift google-cloud-firestore

从Firestore数据库导入数据时遇到问题。

基本上,我使用的是值index,该值是从以前的View Controller中的表视图作为indexPath?.row继承的。当在阵列中使用index时出现致命错误,错误为fatal error: Index out of range

以下代码来自此新的重定向View Controller:

import Firebase

class DetailedSubjectsViewController: UIViewController {

    var index: Int!
    var database: Firestore!
    var subjectsArray = [Subjects]()

    override func viewDidLoad() {
        super.viewDidLoad()

        database = Firestore.firestore()
        loadData()

        let subjects = subjectsArray[index] // fatal error: Index out of range
        labelTitle.text = subjects.name
    }

    func loadData() {
        let uid = Auth.auth().currentUser?.uid
        database.collection("users").document(uid ?? "").collection("subjects").getDocuments { (querySnapshot, error) in
            if let error = error {
                fatalError("Fatal error: \(error.localizedDescription)")
            } else {
                self.subjectsArray = querySnapshot!.documents.compactMap({ Subjects(dictionary: $0.data())})
                }
            }
        }
}

这是上一个View Controller中的代码:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let indexPath = tableviewSubjects.indexPathForSelectedRow
        let indexNumber = indexPath?.row
        let detailedSubjectsViewController = segue.destination as! DetailedSubjectsViewController
        detailedSubjectsViewController.index = indexNumber
    }

有什么办法可以解决此问题?感谢所有帮助!

2 个答案:

答案 0 :(得分:1)

您被困在异步陷阱中。添加完成处理程序。

import Firebase

class DetailedSubjectsViewController: UIViewController {

    var index: Int!
    var database: Firestore!
    var subjectsArray = [Subjects]()

    override func viewDidLoad() {
        super.viewDidLoad()

        database = Firestore.firestore()
        loadData() { [weak self] result in
           switch result {
              case .success(let data):
                  DispatchQueue.main.async {
                     self?.subjectsArray = data
                     if self?.index < data.count {
                       let subject = data[index]
                       self?.labelTitle.text = subject.name
                     }  
                  }  

              case .failure(let error):
                 fatalError("Fatal error: \(error.localizedDescription)")
           }

        }
    }

    func loadData(completion: @escaping (Result<[Subjects],Error>)->Void) {
        let uid = Auth.auth().currentUser?.uid
        database.collection("users").document(uid ?? "").collection("subjects").getDocuments { (querySnapshot, error) in
            if let error = error {
                completion(.failure(error))
            } else {
                let subjects = querySnapshot!.documents.compactMap({ Subjects(dictionary: $0.data())})
                completion(.success(subjects))
            }
        }
    }
}

答案 1 :(得分:0)

对于其中一个,您可以添加防护装置以防发生此问题:

database = Firestore.firestore()
loadData()
guard index < subjectsArray.count else { return }
...

接下来,请注意您的loadData()正在执行数据的异步加载,这就是为什么您有一个在数据完全加载后被调用的回调方法的原因。

在回调之前,subjectArray可能为空(并且是!),因此存在越界问题。

// let subjects = subjectsArray[index] // fatal error: Index out of range
// labelTitle.text = subjects.name
}

func setSubjectTitle() {
  guard index < subjectsArray.count else { return }
  let subject = subjectsArray[index]
  labelTitle.text = subject.name
}

func loadData() {
  let uid = Auth.auth().currentUser?.uid
  database
    .collection("users").document(uid ?? "")
    .collection("subjects").getDocuments { (querySnapshot, error) in
            if let error = error {
                fatalError("Fatal error: \(error.localizedDescription)")
            } else {
                self.subjectsArray = querySnapshot!.documents.compactMap({ Subjects(dictionary: $0.data())})
                }
                self.setSubjectTitle()
            }
        }
}