質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Realm

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

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

解決済

1回答

3415閲覧

Relamでのエラー

退会済みユーザー

退会済みユーザー

総合スコア0

Realm

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

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

0グッド

0クリップ

投稿2018/06/21 15:58

編集2018/06/24 03:28

swift

1class TopViewViewController: UIViewController,UITableViewDataSource,UITableViewDelegate { 2 3 4 @IBOutlet weak var TopViewTabelView: UITableView! 5 //var item = [String]() 6 let ToDo = TopTodo() 7 var todoItem: Results<TopTodo>! 8 9 10 11 override func viewDidLoad() { 12 super.viewDidLoad() 13 14 // 永続化されているデータを取りだす 15 do{ 16 let realm = try Realm() 17 self.todoItem = realm.objects(TopTodo.self) 18 self.TopViewTabelView.reloadData() 19 }catch{ 20 21 } 22 23 navigationController?.navigationBar.prefersLargeTitles = true //これがやりたかった設定やメモ帳のナビゲーションの可変のやつ 24 navigationItem.title = "データベース" 25 TopViewTabelView.tableFooterView = UIView(frame: .zero) 26 self.view.backgroundColor = UIColor.rgb(r: 250, g: 204, b: 125, alpha: 1) 27 TopViewTabelView.frame = CGRect(x: 0, y: 64, width: 375, height: 667) 28 29 } 30 31 override func viewWillAppear(_ animated: Bool) { 32 super.viewWillAppear(animated) 33 TopViewTabelView.reloadData() 34 } 35 36 override func didReceiveMemoryWarning() { 37 super.didReceiveMemoryWarning() 38 // Dispose of any resources that can be recreated. 39 } 40 41 42 @IBAction func addBtr(_ sender: Any) { 43 let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert) 44 45 // OKボタンの設定 46 let okAction = UIAlertAction(title: "OK", style: .default, handler: { 47 (action:UIAlertAction!) -> Void in 48 49 // OKを押した時入力されていたテキストを表示 50 if let textFields = alert.textFields { 51 52 // アラートに含まれるすべてのテキストフィールドを調べる 53 for textField in textFields { 54 // 変数で持つ必要はないのではないでしょうか? 55 let newTodo = TopTodo() 56 newTodo.item = textField.text! 57 do{ 58 let realm = try Realm() 59 60 // トランザクション開始 61 try realm.write({ () -> Void in 62 realm.add(newTodo) 63 print("ToDo Saved") 64 }) 65 // ここでトランザクションが終了 66 67 // ここでtodoItemの更新 68 self.todoItem = realm.objects(TopTodo.self) 69 self.TopViewTabelView.insertRows(at: [IndexPath(row: 0, section: 0)],with: UITableViewRowAnimation.automatic) 70 print(textField.text!) 71 72 }catch{ 73 print("Save is Faild") 74 } 75 } 76 self.TopViewTabelView.reloadData() 77 } 78 }) 79 alert.addAction(okAction) 80 81 // キャンセルボタンの設定 82 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) 83 alert.addAction(cancelAction) 84 85 // テキストフィールドを追加 86 alert.addTextField(configurationHandler: {(textField: UITextField!) -> Void in 87 textField.placeholder = "テキスト" 88 }) 89 alert.view.setNeedsLayout() // シミュレータの種類によっては、これがないと警告が発生 90 91 self.present(alert, animated: true, completion: nil) 92 } 93 94 95 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 96 return todoItem.count 97 98 } 99 100 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 101 let Cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) 102 /*let now = NSDate() // 現在日時の取得 103 104 let dateFormatter = DateFormatter() 105 dateFormatter.locale = NSLocale(localeIdentifier: "en_US") as Locale? // ロケールの設定 106 dateFormatter.dateFormat = "yyyy年MM月dd日 HH:mm"//:ss" // 日付フォーマットの設定 107 108 let deterstring = dateFormatter.string(from: now as Date) 109 print(deterstring) // -> 2014/06/25 02:13:18*/ 110 111 let object = todoItem[indexPath.row] 112 Cell.textLabel?.text = object.item //+ deterstring 113 Cell.detailTextLabel?.text = object.date.description 114 //Cell.detailTextLabel?.text = deterstring 115 116 return Cell 117 } 118 119 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { 120 121 122 if(editingStyle == UITableViewCellEditingStyle.delete) { 123 do{ 124 let realm = try Realm() 125 try realm.write { 126 realm.delete(self.todoItem[indexPath.row]) 127 } 128 TopViewTabelView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.fade) 129 }catch{ 130 } 131 TopViewTabelView.reloadData() 132 } 133 } 134 135}

swift

1import RealmSwift 2 3class TopTodo: Object{ 4 // 管理用 ID。プライマリーキー 5 @objc dynamic var id = 0 6 @objc dynamic var item = "" 7 8 /// 最終更新日時 9 @objc dynamic var date = NSDate() 10 11 //id をプライマリーキーとして設定 12 override static func primaryKey() -> String? { 13 return "id" 14 } 15 16}

困っていること

セルのサブタイトルの更新時間を取得したく、オブジェクトクラスに@objc dynamic var date = NSDate()を追加したところ、numberOfRowsInSectionreturn todoItem.counでエラーが起きてしまった。
以下がエラーの内容です。
Fatal error: Unexpectedly found nil while unwrapping an Optional value
実行すると落ちてしまいます。

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

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

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

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

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

guest

回答1

0

ベストアンサー

その行で Unexpectedly found nil while unwrapping an Optional valueで落ちたと言うことは、todoItemがnilだったということです。

todoItemを設定している処理は

swift

1 do{ 2 let realm = try Realm() 3 self.todoItem = realm.objects(TopTodo.self) 4 self.TopViewTabelView.reloadData() 5 }catch{ 6 7 }

です。
おそらくtodoItemがnilになった原因は、try Realm()の処理がエラーになり、self.todoItem = 〜の処理が実行されずにcatch節に実行が移ったのだと思います。
最悪なのは、do-catchの構文を使っているのに、catch節の中に何も書いていないことです。このため、ここでエラーが発生しているのにエラー処理を何もせず、エラーがなかったことにされ、todoItemがnilのまま続きが動作して質問の箇所でエラーが発生したのだと思います。
せめて、次のようにcatch節でエラーをprintしておけば、try Realm()がエラーになった原因がコンソールメッセージで出力されるはずです。

swift

1 }catch{ 2 print(error) 3 }

そもそも try Realm()がエラーになったら、Realmが一切使えないということなので続行しても仕方がなく、この段階でエラーになった原因をしっかり調べる必要があります。
そのため、通常ここではdo-catchを使わず、次のように try!を使って、
エラー発生時はエラーメッセージを表示してすぐにアプリを停止させるのが一般的だと思います。

swift

1 let realm = try! Realm() 2 self.todoItem = realm.objects(TopTodo.self) 3

try Realm()がエラーになった原因については、そのエラーメッセージを確認しないと正確なことはわかりませんが、上記の修正をして表示されたエラーメッセージにMigration is requiredといったようなメッセージが出ていたら、

オブジェクトクラスに@objc dynamic var date = NSDate()を追加した

ということなので、前回実行した時とデータ構造が変わり、前回のアプリ実行で保存していたデータが使用できなくてエラーになったということだと思います。

このアプリがまだユーザーにリリースされていないものであれば、今自分がテストに使っているシミュレータや実機からこのアプリを削除して再実行するだけで以前に保存していたデータは削除されるので、エラーは解消されると思います。

もし、既にこのアプリがユーザーにリリースされていて、今回はそのアプリのバージョンアップでデータ項目を追加しようとしているのなら、ユーザーが保存していたデータを引き継いで新しいデータ構造で処理できるよう「マイグレーション」という処理を実施する必要があります。

投稿2018/06/25 01:48

TakeOne

総合スコア6299

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

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

退会済みユーザー

退会済みユーザー

2018/06/25 04:53

懇切にご教授していただき有難うございます。 解決できました。 今回はまだ開発中の段階でしたのでマイグレーションを行う必要はありませんでした。 しかし、マイグレーションという処理は今後必要になっていくと思いますので勉強したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問