Исправить фатальную ошибку: Индекс вне диапазона в массивах - PullRequest
0 голосов
/ 10 июня 2019

У меня возникла проблема при импорте данных из моей базы данных Firestore.

По сути, я использую значение index, которое было перенесено из табличного представления в предыдущем контроллере представления как 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 ]

1 голос
/ 10 июня 2019

Вы попали в Асинхронную ловушку .Добавьте обработчик завершения.

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))
            }
        }
    }
}
0 голосов
/ 10 июня 2019

Например, вы можете добавить охранника в случае возникновения этой проблемы:

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()
            }
        }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...