🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Realm

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

4235閲覧

[swift][Realm] Index 0 is out of bounds (must be less than 0).

Kaguya_4869

総合スコア117

Realm

RealmとはSQLiteやCore Dataに代わるモバイルデータベースです。iOSとAndroidの両方でサポートされています。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2021/02/05 10:36

編集2021/02/05 23:06

#質問したいこと
こんにちは。お世話になっております。
現在、Realmを使用したTodoアプリを作成しております。
今まではUserdefaultsを使用していた部分をRealmで保存したいのですが、
タイトルにもあるように、
Index 0 is out of bounds (must be less than 0).
とエラーが出て落ちてしまいます。
カレンダー(FSCalendar)を使用したアプリなのですが、一番最初にtodoを保存した時にカレンダーで日付を選択しても落ちないのですが、次に保存する時に、最初に保存した時と日付が違うと、2回目に保存したtodoの日付をカレンダー上で選択すると、落ちてしまいます。
例)
①2021/2/5にtodoを保存
②カレンダー2021/2/5を選択
③問題なくtableViewに表示される
④2021/2/10にtodoを保存(保存は問題なくできています)
⑤カレンダー2021/2/10を選択
⑥**Index 0 is out of bounds (must be less than 0).**というエラーが出て落ちる。
#コード

Swift

1//ViewController 2import UIKit 3import FSCalendar 4import RealmSwift 5class ViewController: UIViewController,FSCalendarDelegate,FSCalendarDataSource,FSCalendarDelegateAppearance, UIScrollViewDelegate, UIGestureRecognizerDelegate{ 6var ImItems: Results<ImportantDate>! 7 8private var dataSource: [AddDate] = [AddDate]() { 9 didSet { 10 contentVC.tableView.reloadData() 11 } 12 } 13func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 14 if indexPath.section == 0 { 15 let cell = tableView.dequeueReusableCell(withIdentifier: ImportantDayTableViewCell.reuseIdentifier, for: indexPath) as! ImportantDayTableViewCell 16 guard let count = ImItems?.count, indexPath.row < count else { return cell } 17 try! realm.write{ 18 ImItems[indexPath.row].title = self.dataSource[indexPath.row].title 19 ImItems[indexPath.row].dateDescription = self.dataSource[indexPath.row].content 20 ImItems[indexPath.row].date = self.dataSource[indexPath.row].date 21 ImItems[indexPath.row].pin = self.dataSource[indexPath.row].pin 22 if memo.pin == true { 23 cell.setupCell(title: self.ImItems[indexPath.row].title, 24 content: self.ImItems[indexPath.row].dateDescription, 25 date: self.ImItems[indexPath.row].date, 26 pin: false) 27 } 28 if memo.pin == false { 29 cell.setupCell(title: self.ImItems[indexPath.row].title, content: self.ImItems[indexPath.row].dateDescription, date: self.ImItems[indexPath.row].date, pin: true) 30 31 } 32 33 return cell 34 } 35 } 36}

Swift

1//Realmで新しく保存するモデル 2import Foundation 3import RealmSwift 4 5class ImportantDate: Object { 6 7 @objc dynamic var title: String = "" 8 @objc dynamic var dateDescription: String = "" 9 @objc dynamic var date = String() 10 @objc dynamic var pin: Bool = false 11}

Swift

1//Userdefaultsで保存してた時のモデル 2import Foundation 3 4struct AddDate: Codable { 5 var title: String 6 var content: String 7 var date: String 8 var pin: Bool 9} 10

2ヶ月ほど悩んでいるのですが、なかなか解決できていません。
よろしくお願いいたします。

#追記

Swift

1func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 2 if ImItems == nil { 3 return 0 4 } else { 5 return ImItems.count 6 } 7 }

FSCalendarで日付をタップした際

Swift

1func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { 2 let tmpDate = Calendar(identifier: .gregorian) 3 let year = tmpDate.component(.year, from: date) 4 let month = tmpDate.component(.month, from: date) 5 let day = tmpDate.component(.day, from: date) 6 7 UserDefaults.standard.set(year, forKey: "year") 8 UserDefaults.standard.set(month, forKey: "month") 9 UserDefaults.standard.set(day, forKey: "day") 10 let formatter = DateFormatter() 11 formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "yyyy/M/d", options: 0, locale: Locale(identifier: "ja_JP")) 12 let dateStr = formatter.string(from: date) 13 dateLabel.text = dateStr 14 UserDefaults.standard.set(dateLabel.text, forKey: "date") 15 print("calendar dateStr: (dateStr)") 16 let realm = try! Realm() 17 self.ImItems = realm.objects(ImportantDate.self).filter("date == %@", dateStr) 18 self.items = realm.objects(Event.self).filter("date == %@", dateStr) 19 20 contentVC.tableView.reloadData() 21 22 let dateUdf = UserDefaults.standard.object(forKey: "date") as! String 23 let dateUtils = DateUtils.dateFromString(string: dateUdf, format: "yyyy/M/d") 24 weekCalendar.select(dateUtils) 25 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TsukubaDepot

2021/02/05 13:33

全体的なコードをみないと断定できないのですが、TableView の DataSource として返している行数が var ImItems: Results<ImportantDate>! と一致していないということはないでしょうか。 また、 ImItems[indexPath.row].title = self.dataSource[indexPath.row].title この辺りのコードはどのような動作を意図していらっしゃるのでしょうか。
Kaguya_4869

2021/02/05 23:02 編集

ありがとうございます。 DataSourceとして返している行数は追記いたしましたとおり、return ImItems.countとしています。 > ImItems[indexPath.row].title = self.dataSource[indexPath.row].title この辺りのコードはどのような動作を意図していらっしゃるのでしょうか。 もともとUserdefaultsとして保存していたものをRealmとして保存したいため、Userdefaultsの中身をrealmに保存するというコードを書きたかったのですが、どのように書けば良いか分からなかったので、そのように記述しました。 説明・理解不足で申し訳ありません。 よろしくお願い致します。
TsukubaDepot

2021/02/06 00:24

>もともとUserdefaultsとして保存していたものをRealmとして保存したいため、Userdefaultsの中身をrealmに保存するというコードを書きたかったのですが、どのように書けば良いか分からなかったので、そのように記述しました。 それまでUserDefaults に保存していたデータを Relms に移行するのであれば、通常は移行処理を行うことになるかと思います。 AppDelegate.swift などの適切な場所で、UserDefaults に保存されていたデータを、Realm のデータとして一括登録し、UserDefault のデータは消したり、あるいは移行済みのフラグを立てるなどして、それ以降は一切UserDefaults は触らないようにする必要があります。 ざっとしかコードを拝見していませんが、UserDefaults に保存しつつ Realm に保存するという処理になっていますが、それだと両者に保存することになってしまいます。そうではなく、Realmだ気に保存するような処理にする必要がありますし、realm.write で保存する必要もあります。コードを拝見すると、イベントの新規登録部分にobjectの追加部分がありませんが、そのあたりはどこかで処理されているのでしょうか。 エラーが出ている行を詳しくご説明していただいていないので推定なのですが、Relms にオブジェクトを登録しないまま > ImItems[indexPath.row].title = self.dataSource[indexPath.row].title という処理を行なっているためインデックス違反が起きているのではないでしょうか。 というか、Realmのマネージドオブジェクトのインデックスを直接指定して書き込むのも良くない様な気がします。
Kaguya_4869

2021/02/07 02:29

ご指摘ありがとうございます。 自分のコードをもう一度見直してみたところ、マイグレーション 処理をAppDelegateに記述していなかったのと、todoを追加する際に、realmとUserdefaultsに追加していたので、Userdefaultsの処理を全て消去してから読み込み、追加の部分でUserdefaultsに触らないようにしたところ、エラーが出ることなく、追加できました!ありがとうございます。
TsukubaDepot

2021/02/07 03:17

解決できましたでしょうか。 解決できたのであれば、自己解決という形でこの質問を閉じていただければと思います。 ご協力、よろしくお願い致します。
guest

回答1

0

自己解決

質問への追記・修正の依頼に書いてある方法で解決できました。

投稿2021/02/28 22:21

Kaguya_4869

総合スコア117

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問