前提・実現したいこと
Swiftで友達を登録・管理するアプリを作っており、データをCollectionViewに表示したいです。
Realm Swiftを使っており、名前や写真に加えてChartsでレーダーチャートも登録・表示したいです。
エラーは、情報入力画面で登録のボタンを押すと、CollectionViewに戻らずに"Index out of range"が出ます。
毎回ではなく、データ登録が何回かうまく行く時もあり、またCollectionViewのCellからレーダーチャート表示を除くとエラーは出ません。
原因究明方法を教えていただけると嬉しいです。
発生している問題・エラーメッセージ
Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift, line 444
エラーはChartsのRadarChartRenderer.swiftファイル124行目にに出ます。
let accessibilityLabel = accessibilityAxisLabelValueTuples[j].0
該当のソースコード
swift
1import UIKit 2import RealmSwift 3 4class Mate: Object { 5 @objc dynamic var id = "" 6 @objc dynamic var name = "" 7 @objc dynamic var photo = Data() 8 @objc dynamic var paranum = 6 9 @objc dynamic var lab_1 = "" 10 @objc dynamic var lab_2 = "" 11 @objc dynamic var lab_3 = "" 12 @objc dynamic var lab_4 = "" 13 @objc dynamic var lab_5 = "" 14 @objc dynamic var lab_6 = "" 15 @objc dynamic var val_1: Double = 0 16 @objc dynamic var val_2: Double = 0 17 @objc dynamic var val_3: Double = 0 18 @objc dynamic var val_4: Double = 0 19 @objc dynamic var val_5: Double = 0 20 @objc dynamic var val_6: Double = 0 21}
swift
1import UIKit 2import Charts 3import RealmSwift 4 5class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { 6 7 @IBOutlet weak var collectionView: UICollectionView! 8 9 let realm = try! Realm() 10 var mates = try! Realm().objects(Mate.self) 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 // Do any additional setup after loading the view. 15 collectionView.dataSource = self 16 mates = try! Realm().objects(Mate.self) 17 } 18 19 //セルの数を設定 20 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 21 return mates.count 22 } 23 24 //セルの情報を設定 25 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 26 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell 27 let mate = mates[indexPath.row] 28 var uiImage: UIImage? = UIImage(data: mate.photo as Data) 29 let vs = [mate.val_1, mate.val_2, mate.val_3, mate.val_4, mate.val_5, mate.val_6] 30 let ls = [mate.lab_1, mate.lab_2, mate.lab_3, mate.lab_4, mate.lab_5, mate.lab_6] 31 let no = mate.paranum 32 cell.setup(name: mate.name, icon: uiImage!, vals: vs, labs: ls, num: no) 33 return cell 34 } 35}
swift
1import UIKit 2import Charts 3 4class CollectionViewCell: UICollectionViewCell { 5 @IBOutlet weak var cellName: UILabel! 6 @IBOutlet weak var cellImage: UIImageView! 7 @IBOutlet weak var cellChart: RadarChartView! 8 9 func setup(name: String, icon: UIImage, vals: [Double], labs: [String], num: Int){ 10 cellName.text = name 11 cellImage.image = icon 12 setChart(values: vals, labels: labs, paraNum: num) 13 } 14 15 func setChart(values: [Double], labels: [String], paraNum: Int){ 16 var dataEntries: [RadarChartDataEntry] = [] 17 for i in 0..<paraNum { 18 let dataEntry = RadarChartDataEntry(value: values[i], data: i) 19 dataEntries.append(dataEntry) 20 } 21 let set = RadarChartDataSet(dataEntries) 22 let xAxis = cellChart.xAxis 23 let chartFormatter = RadarChartFormatter(labels: labels) 24 xAxis.valueFormatter = chartFormatter 25 cellChart.xAxis.valueFormatter = xAxis.valueFormatter 26 cellChart.data = RadarChartData(dataSet: set) 27 } 28} 29 30private class RadarChartFormatter: NSObject, IAxisValueFormatter { 31 32 var labels: [String] = [] 33 34 func stringForValue(_ value: Double, axis: AxisBase?) -> String { 35 if Int(value) < labels.count { 36 return labels[Int(value) % labels.count] 37 }else{ 38 return String("") 39 } 40 } 41 init(labels: [String]) { 42 super.init() 43 self.labels = labels 44 } 45}
swift
1import UIKit 2import RealmSwift 3import Charts 4 5class InputViewController: UIViewController, UIImagePickerControllerDelegate & UINavigationControllerDelegate { 6 7 @IBOutlet weak var nameLabel: UILabel! 8 @IBOutlet weak var imageView: UIImageView! 9 @IBOutlet weak var radarChart: RadarChartView! 10 @IBOutlet weak var paraView: UIView! 11 12 var inputPhoto = UIImage(named: "sample") 13 var inputName = "" 14 var inputLab_1 = "" 15 var inputLab_2 = "" 16 var inputLab_3 = "" 17 var inputLab_4 = "" 18 var inputLab_5 = "" 19 var inputLab_6 = "" 20 var inputVal_1: Double = 0 21 var inputVal_2: Double = 0 22 var inputVal_3: Double = 0 23 var inputVal_4: Double = 0 24 var inputVal_5: Double = 0 25 var inputVal_6: Double = 0 26 var labs = ["", "", "", "", "", ""] 27 var vals:[Double] = [0, 0, 0, 0, 0, 0] 28 29 override func viewDidLoad() { 30 super.viewDidLoad() 31 nameLabel.text = inputName 32 imageView.image = inputPhoto 33 labs = [inputLab_1, inputLab_2, inputLab_3, inputLab_4, inputLab_5, inputLab_6] 34 vals = [inputVal_1, inputVal_2, inputVal_3, inputVal_4, inputVal_5, inputVal_6] 35 setChart(values: vals, labels: labs, paraNum: inputParaNum) 36 } 37 38 //登録ボタン 39 @IBAction func okBtm(_ sender: Any) { 40 let realm = try! Realm() 41 let newData = Mate() 42 newData.name = inputName 43 newData.photo = (imageView.image?.jpegData(compressionQuality: 0.25))! as Data 44 newData.paranum = inputParaNum 45 newData.lab_1 = labs[0] 46 newData.lab_2 = labs[1] 47 newData.lab_3 = labs[2] 48 newData.lab_4 = labs[3] 49 newData.lab_5 = labs[4] 50 newData.lab_6 = labs[5] 51 newData.val_1 = vals[0] 52 newData.val_2 = vals[1] 53 newData.val_3 = vals[2] 54 newData.val_4 = vals[3] 55 newData.val_5 = vals[4] 56 newData.val_6 = vals[5] 57 try! realm.write { 58 realm.add(newData) 59 } 60 self.dismiss(animated: true, completion: nil) 61 } 62 63private class RadarChartFormatter: NSObject, IAxisValueFormatter { 64 65 var labels: [String] = [] 66 67 func stringForValue(_ value: Double, axis: AxisBase?) -> String { 68 if Int(value) < labels.count { 69 return labels[Int(value)] 70 }else{ 71 return String("") 72 } 73 } 74 75 init(labels: [String]) { 76 super.init() 77 self.labels = labels 78 } 79}
swift
1import UIKit 2 3class ParaViewController: UIViewController { 4 5 @IBOutlet weak var lab_1: UITextField! 6 @IBOutlet weak var lab_2: UITextField! 7 @IBOutlet weak var lab_3: UITextField! 8 @IBOutlet weak var lab_4: UITextField! 9 @IBOutlet weak var lab_5: UITextField! 10 @IBOutlet weak var lab_6: UITextField! 11 @IBOutlet weak var val_1: UITextField! 12 @IBOutlet weak var val_2: UITextField! 13 @IBOutlet weak var val_3: UITextField! 14 @IBOutlet weak var val_4: UITextField! 15 @IBOutlet weak var val_5: UITextField! 16 @IBOutlet weak var val_6: UITextField! 17 18 var childVals:[Double] = [0, 0, 0, 0, 0, 0] 19 var childLabs = ["A", "B", "C", "D", "E", "F"] 20 var childParaNum = 6 21 22 override func viewDidLoad() { 23 super.viewDidLoad() 24 } 25 26 override func viewWillAppear(_ animated: Bool) { 27 let parent = self.parent as! InputViewController 28 childVals = parent.vals 29 childLabs = parent.labs 30 childParaNum = parent.inputParaNum 31 } 32 33 @objc func changeDatas(){ 34 changeData(text: val_1.text!, dataNum: 0) 35 changeData(text: val_2.text!, dataNum: 1) 36 changeData(text: val_3.text!, dataNum: 2) 37 changeData(text: val_4.text!, dataNum: 3) 38 changeData(text: val_5.text!, dataNum: 4) 39 changeData(text: val_6.text!, dataNum: 5) 40 let parent = self.parent as! InputViewController 41 parent.setChart(values: childVals, labels: childLabs, paraNum: childParaNum) 42 parent.vals = childVals 43 } 44 45 func changeData(text:String, dataNum:Int){ 46 if text == "" { 47 childVals[dataNum] = 0 48 }else{ 49 childVals[dataNum] = Double(text)! 50 } 51 } 52 53 func changeLabels(){ 54 childLabs[0] = String(lab_1.text!) 55 childLabs[1] = String(lab_2.text!) 56 childLabs[2] = String(lab_3.text!) 57 childLabs[3] = String(lab_4.text!) 58 childLabs[4] = String(lab_5.text!) 59 childLabs[5] = String(lab_6.text!) 60 let parent = self.parent as! InputViewController 61 parent.labs = childLabs 62 }
試したこと
chatrsアップデート・再インストール
レーダーチャート表示無しの場合の確認⇨エラーは出ない
様々なパターンのデータ登録
補足情報(FW/ツールのバージョンなど)
Xcode 12.4
Swift 5
RealmSwift 10.5.1
Charts 3.6.0
あなたの回答
tips
プレビュー