前提・実現したいこと
コレクションビューのセルに、firestoreに格納しているセル名を表示したいです。
発生している問題・エラーメッセージ
エラーメッセージ Thread 1: Fatal error: Index out of range
上記のエラーメッセージが発生。
(通常、配列に入れる要素の数等がおかしい場合に出るエラーとのことです)
firestore上のドキュメントからクエリで(サブコレクションの)フィールド情報を取得して配列(mtIds)に格納。
同じように、セル名に該当する情報も配列(namedata)に格納。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
上記のセルの設定で、「namedata」配列を使ってセル名を入力しようとするとエラーが発生してしまいます。
該当のソースコード
Swift
1 2 3class SecondViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { 4 5 @IBOutlet weak var collectionView: UICollectionView! 6 7 private var namedata: [String] = [] 8 private var mtIds: [Int] = [] 9 10 var selectedmtd = Int() 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 15 self.loadData() 16 17 // レイアウトを調整 18 collectionView.contentInset = UIEdgeInsets(top: 12, left: 24, bottom: 16, right: 24) 19 20 let layout = UICollectionViewFlowLayout() 21 layout.minimumInteritemSpacing = 8 22 collectionView.collectionViewLayout = layout 23 24 } 25 26 27 // MARK: UICollectionViewDataSource 28 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 29 return mtIds.count // 表示するセルの数 30 } 31 32 33 // MARK: UICollectionViewDataSource 34 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 35 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) // 表示するセルを登録(先程命名した"Cell") 36 cell.backgroundColor = .white // セルの色 37 38 let bgimage = cell.contentView.viewWithTag(2) as! UIImageView 39 bgimage.image = UIImage(named: "nobadge") 40 41 let celllabel = cell.contentView.viewWithTag(1) as! UILabel 42 celllabel.text = namedata[indexPath.row] 43 44 return cell 45 } 46 47 // MARK: UICollectionViewDelegateFlowLayout 48 49 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 50 return CGSize(width: cellWidth, height: 120) 51 } 52 53 private var cellWidth: CGFloat { 54 let availableWidth = collectionView.bounds.inset(by: collectionView.adjustedContentInset).width 55 let interColumnSpace = CGFloat(20) 56 let numColumns = CGFloat(4) 57 let numInterColumnSpaces = numColumns - 1 58 59 return ((availableWidth - interColumnSpace * numInterColumnSpaces) / numColumns).rounded(.down) 60 } 61 62 63 private func loadData() { 64 65 let db = Firestore.firestore() 66 67 let user = Auth.auth().currentUser 68 69 db.collection("users").document(user!.uid).collection("history").getDocuments() { (querySnapshot, err) in 70 if let err = err { 71 // エラー時の処理 72 print("Error getting documents: (err)") 73 return 74 } 75 self.mtIds = querySnapshot!.documents.compactMap { $0.data()["historyid"] as? Int } 76 77 78 //---------------------------- 79 for id in self.mtIds { 80 db.collection("mtinfo").whereField("mtid", isEqualTo: id).getDocuments() { (querySnapshot, err) in 81 if let err = err { 82 print("[loadData] Error getting documents: (err)") 83 } else { 84 for document in querySnapshot!.documents { 85 self.namedata.append(document.data()["name"] as! String) 86 } 87 } 88 } 89 } 90 //---------------------------- 91 92 // コレクションビューを更新 93 self.collectionView.reloadData() 94 95 } 96 97 } 98 99} 100 101 102 103
試したこと
「namedata」へのデータ格納が終わる前に、エラー発生しているように見えるので、エラーが発生しているであろう部分をコメントアウトすると、エラーが発生せず、かつ「namedata」配列に正しくデータが格納されます。
celllabel.text = namedata[indexPath.row]
loadData() の位置をviewdidload()の最初の方に持ってきたりしましたが、あまり意味はなく・・
処理順の問題なのか、もっと単純なミスなのか、どうしても原因が分からないのでご教授いただけると本当に助かります。
どうぞよろしくお願いいたします。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
あなたの回答
tips
プレビュー