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

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

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

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

Swift

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

Q&A

0回答

335閲覧

【swift】 FCalenderにてカレンダー上部の日付をクリックするとエラーが起きる解決方法

yamadayeah90

総合スコア6

Realm

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

Swift

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

0グッド

0クリップ

投稿2022/06/19 12:33

MacOS(macOS Monterey12.0.1)、Xcode(13.1)、swift(5.5.1)
実行環境 シミュレーション(iPhone12pro)

現在、FCalenderを利用してタスクを表示するアプリを開発しているます。
カレンダー下部を選択すると、ラベルに対して選択した年月日をYYYY年MM月DD日形式に変換して表示するという処理を実装しているのですが、なぜか画面下部を選択するとラベルに日時を表示するメソッドを実行せずにデータベースに選択日時をラベルからデータを持ってくるメソッドを実行してしまいます。
そのため下記のエラーになってしまいます。

どのようにしたらカレンダーにて日付けをタッチしたら必ずラベルに対して日時を表示してからデータベースからデータを持ってくるメソッドを実行できるようになりますでしょうか?

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

すいません原因がよくわからないので少し長いですがソースを貼ります。

swift

1 //選択日付を表示する 2 func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { 3 //選択日付をフォーマット 4 let tmpDate = Calendar(identifier: .gregorian) 5 let year = tmpDate.component(.year, from: date) 6 let month = tmpDate.component(.month, from: date) 7 let day = tmpDate.component(.day, from: date) 8 let formatDate = getFormattedDateString(dateString: "\(year)\(month)\(day)") 9 labelDate.text = formatDate 10 TableView.reloadData() 11 } 12 13 func getFormattedDateString(dateString: String, from fromFormat: String = "yyyyMdd", to toFormat: String = "yyyy年MM月dd日") -> String? { 14 let dateFormatter = DateFormatter() 15 dateFormatter.locale = .current 16 dateFormatter.dateFormat = fromFormat 17 guard let date = dateFormatter.date(from: dateString) else { return nil } 18 dateFormatter.dateFormat = toFormat 19 return dateFormatter.string(from: date) 20 } 21 22 // 任意の日付に点マークをつける 23 func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int{ 24 25 let formatter = DateFormatter() 26 formatter.dateFormat = "yyyy年MM月dd日" 27 formatter.calendar = Calendar(identifier: .gregorian) 28 formatter.timeZone = TimeZone.current 29 formatter.locale = Locale.current 30 let calendarDay = formatter.string(from: date) 31 32 // Realmオブジェクトの生成 33 let realm = try! Realm() 34 // 参照(全データを取得) 35 let todos = realm.objects(calender.self) 36 37 if todos.count > 0 { 38 for i in 0..<todos.count { 39 if i == 0 { 40 datesWithEvents = [todos[i].date] 41 } else { 42 datesWithEvents.insert(todos[i].date) 43 } 44 } 45 } else { 46 datesWithEvents = [] 47 } 48 return datesWithEvents.contains(calendarDay) ? 1 : 0 49 } 50 51 var selectdate:String? 52 //プラスボタンクリック 53 @IBAction func plusBottun(_ sender: Any) { 54 55 selectdate = labelDate.text 56 //画面遷移(スケジュール登録ページ) 57 // SubViewController へ遷移するために Segue を呼び出す 58 performSegue(withIdentifier: "out",sender: nil) 59 } 60 61 62 63 @IBAction func MinusButton(_ sender: Any) { 64 selectdate = labelDate.text 65 //画面遷移(スケジュール登録ページ) 66 // SubViewController へ遷移するために Segue を呼び出す 67 performSegue(withIdentifier: "income",sender: nil) 68 } 69 70 // Segue 準備 71 override func prepare(for segue: UIStoryboardSegue, sender: Any!) { 72 //プラスボタンクリック時 73 if (segue.identifier == "out"){ 74 let calender = (segue.destination as? out)! 75 //選択した日付けを次画面へ 76 calender.selectdate = selectdate 77 } else if (segue.identifier == "income") { 78 let calender = (segue.destination as? income)! 79 calender.selectdate = selectdate 80 } 81 } 82 83 84 85 //データベース上に保存されているデータを配列に格納する。 86 func getModel(date:String) -> [[String:String]] { 87 let realm = try! Realm() 88 let results = realm.objects(calender.self).filter("date == %@",date) 89 var param: [[String:String]] = [] 90 for result in results { 91 param.append(["reason": result.reason, 92 "money": String(result.AmountOfMoney), 93 "date": result.date, 94 "flag": result.flag 95 ]) 96 97 } 98 return param 99 } 100 101 //セルの編集許可 102 func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool 103 { 104 return true 105 } 106 107 func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { 108 let action = UIContextualAction(style: .destructive, 109 title: "削除") { (action, view, completionHandler) in 110 self.showAlert(deleteIndexPath: indexPath) 111 completionHandler(true) 112 } 113 action.backgroundColor = .red 114 let configuration = UISwipeActionsConfiguration(actions: [action]) 115 return configuration 116 } 117 118 func showAlert(deleteIndexPath indexPath: IndexPath) { 119 let date = labelDate.text! 120 let dialog = UIAlertController(title: "削除", 121 message: "削除してよろしいですか?", 122 preferredStyle: .alert) 123 var array = getModel(date: date) 124 dialog.addAction(UIAlertAction(title: "削除", style: .default, handler: { (_) in 125 array.remove(at: indexPath.row) 126 self.deleteModel(selectedDate: date, indexPath: indexPath.row) 127 self.TableView.deleteRows(at: [indexPath], with: .automatic) 128 129 })) 130 dialog.addAction(UIAlertAction(title: "やめる", style: .cancel, handler: nil)) 131 self.present(dialog, animated: true, completion: nil) 132 } 133} 134 135extension calendar: UITableViewDelegate, UITableViewDataSource { 136 //セルの個数を返すメソッド 137 func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int { 138 let length:Int = getModel(date: labelDate.text!).count 139 return length 140 141 142 } 143 144 //セクション内に表示するセルのテキストを返すメソッド 145 func tableView(_ tableView: UITableView, cellForRowAt IndexPath: IndexPath) -> UITableViewCell { 146 let cell = TableView.dequeueReusableCell(withIdentifier: "calendarCell", for: IndexPath) 147 let data = getModel(date: labelDate.text!)[IndexPath.row] 148 let reasonLabel = cell.contentView.viewWithTag(1) as! UILabel 149 let dateLabel = cell.contentView.viewWithTag(2) as! UILabel 150 let moneyLabel = cell.contentView.viewWithTag(3) as! UILabel 151 //支出なら色を変える 152 if(data["flag"] == "0"){ 153 reasonLabel.textColor = UIColor.red 154 dateLabel.textColor = UIColor.red 155 moneyLabel.textColor = UIColor.red 156 } 157 if let reason = data["reason"]?.description, 158 let date = data["date"]?.description, 159 let money = data["money"]?.description { 160 reasonLabel.text = reason 161 dateLabel.text = date 162 moneyLabel.text = "\(money)円" 163 } 164 165 return cell 166 } 167 168 169 170 171 172 173 174 func deleteModel(selectedDate: String, indexPath: Int) { 175 let realm = try! Realm() 176 let results = realm.objects(calender.self).filter("date == '\(selectedDate)'") 177 do { 178 try realm.write { 179 realm.delete(results[indexPath]) 180 getModel(date: labelDate.text!) 181 } 182 } catch { 183 print("delete data error.") 184 } 185 } 186} 187

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

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

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

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

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

TakeOne

2022/06/25 00:03 編集

FCalendarではなくFSCalendarを利用しているのだと思いますが、「なぜか画面下部を選択するとラベルに日時を表示するメソッドを実行せずにデータベースに選択日時をラベルからデータを持ってくるメソッドを実行してしまいます。」という説明がよくわかりませんでした。やりたいことは、カレンダーの日付をタッチしたらデータベースからその日付のデータを読み込んでTableViewに表示したいということだと思いますが、「画面下部を選択すると」というのは、カレンダーの日付をタッチする操作とは別の操作をした場合にエラーが発生するということですか? その「画面の下部」には何が表示されていて何を選択するとエラーが発生するのでしょうか? また、「ラベルに日時を表示するメソッドを実行せずに」というのは、具体的にどのメソッド名が実行されることを期待しているのですか? また、「データベースに選択日時をラベルからデータを持ってくるメソッドを実行してしまいます」というのは具体的にどのメソッド名が実行されてしまうと言っているのでしょうか? そして、「Unexpectedly found nil while unwrapping an Optional value」のエラーは、具体的にどの行で発生しているのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問