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

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

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

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

Swift

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

Q&A

解決済

2回答

944閲覧

【Swift-Realm・Charts】X軸に対応するY軸の値がない場合のグラフの描画の方法を教えてください

miyuki

総合スコア23

Realm

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

Swift

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

0グッド

0クリップ

投稿2023/03/29 10:29

実現したいこと

X軸に日付、Y軸に値を入れたグラフを作ろうとしています。(ライブラリはChartsを利用)
X軸に1番初めの日から1日ずつずらした日付を入れて、Y軸にはそれに対応する値(ない場合もある)を入れようと考えています。

イメージとしては以下の画像の通りで、値が入力されていない日は無視して、値が入力されている日のデータのみを折れ線グラフで繋ぐイメージです。
イメージ説明

X軸で使う、日にちを1日ずつずらしたDate型の配列は保持できているのですが、Y軸で使いたい、日付に応じたデータ(下記percentにあたる値)が適切に代入されず、以下のようなエラーが出てしまいました。
(ChartsではY軸の値としてnilを使うことができないそうなので、そもそもこのコードの定義自体間違っているのかもしれないです)

上記イメージのようなグラフを作りたい場合、どのようにX軸・Y軸の値を定義し、描画していけば良いのでしょうか。下記のようにX軸の日付データに対応する値を1つずつ代入する方法ではChartsを扱う上で誤りなのでしょうか。ご教授いただけますと大変ありがたいです。

発生している問題・エラーメッセージ

下記ソースコード18行目で

Comparing non-optional value of type 'Results<Post>' to 'nil' always returns true

となってしまい、そのままコードを実行させると

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

とエラーが出ます。

該当のソースコード

Swift

1var points = try! Realm().objects(Post.self).sorted(byKeyPath: "date", ascending: true) 2//X軸日付データ 3var date: [Date] = [] 4//Y軸値データ 5var percent: [Int?] = [] 6 7var firstPost = points.first?.date 8var lastPost = points.last?.date 9//経過日数 10var dateInterval: Int = Int(lastPost!.timeIntervalSince(firstPost!)) / (24 * 60 * 60) 11var i = 0 12var detailDate = Date() 13repeat{ 14 detailDate = Calendar.current.date(byAdding: .day, value: i , to: firstPost!)! 15 var predicate = NSPredicate(format: "date == %@", detailDate as CVarArg) 16 var result = realm.objects(Post.self).filter(predicate) 17 //もしpointsの中にdetailDateと同じ日付がある場合 18 if result != nil{ 19 percent.append(Int(result.first!.percent)) 20 } else{ 21 percent.append(nil) 22 } 23 print(result) 24 print(detailDate) 25 date.append(detailDate) 26 i += 1 27} while i < dateInterval + 1

Swift

1import RealmSwift 2class Post: Object{ 3 @objc dynamic var id = 0 4 @objc dynamic var percent = "" 5 @objc dynamic var date = Date() 6}

補足情報(FW/ツールのバージョンなど)

Xcode 14.1
Realm 5.1.0

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

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

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

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

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

guest

回答2

0

自己解決

下記のURLを参考にしたところ、解決することができました。
nilを代入する処理に関して、KEMONO_PANTSU_kさんにご教授いただきました。コメント欄に記載されている通りです。
https://medium.com/@skipadu/using-realm-and-charts-with-swift-3-in-ios-10-40c42e3838c0

Swift

1import UIKit 2import Charts 3import RealmSwift 4 5class viewController: UIViewController { 6 weak var axisFormatDelegate: AxisValueFormatter? 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 axisFormatDelegate = self 10 } 11 func createChartView(page: Int){ 12 var lineDateEntry = [ChartDataEntry]() 13 let yAxis = getPercentFromDatabase() 14 for i in 0..<yAxis.count { 15 let timeIntervalForDate: TimeInterval = yAxis[i].date.timeIntervalSince1970 16 let dataEntry = ChartDataEntry(x: Double(timeIntervalForDate), y: Double(yAxis[i].percent)!) 17 lineDateEntry.append(dataEntry) 18 } 19 let chartDataSet = LineChartDataSet(lineDateEntry) 20 let chartData = LineChartData(dataSet: chartDataSet) 21 lineChartView.data = chartData 22 let xAxis = lineChartView.xAxis 23 xAxis.valueFormatter = axisFormatDelegate 24 } 25 26 func getPercentFromDatabase() -> Results<Post>{ 27 do { 28 let realm = try Realm() 29 return realm.objects(Post.self) 30 } catch let error as NSError { 31 fatalError(error.localizedDescription) 32 } 33 } 34 35} 36extension ViewController: AxisValueFormatter { 37 38 func stringForValue(_ value: Double, axis: AxisBase?) -> String { 39 let dateFormatter = DateFormatter() 40 dateFormatter.dateFormat = "MM/dd" 41 return dateFormatter.string(from: Date(timeIntervalSince1970: value)) 42 } 43}

投稿2023/03/29 15:19

編集2023/03/29 15:22
miyuki

総合スコア23

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

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

退会済みユーザー

退会済みユーザー

2023/03/30 00:13

すみません、再現確認しようと環境を設定していたのですが、 CocoaPodsを使うのが久しぶりでなかなか進みませんでした・・ でも、自己解決したようで何よりです。 x軸の値はtimeIntervalSince1970を使って、 AxisValueFormatterで表記を変えてあげる感じになるのですね。 勉強になります!
miyuki

2023/03/30 06:48 編集

とんでもないです。。わざわざ確認してくださり非常に心強かったです!コメントまでありがとうございました!!
guest

0

Comparing non-optional value of type 'Results<Post>' to 'nil' always returns true
(機械翻訳)Results<Post>」型の非オプション値と「nil」を比較すると、常に真を返す

このエラーはfilterした結果(result)の型がオプショナルではない
('Results<Post>'型は?がついていないのでnilの可能性がないですね)
にもかかわらず、if result != nilのようにnilと比較していることが原因だと思います。
常に真(true)になるのでifが無駄になっています、ということだと思います。

https://www.mongodb.com/docs/realm/sdk/swift/crud/filter-data/


Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
(機械翻訳)スレッド1:致命的なエラーです: Optional値のアンラップ中に予期せずnilを発見した。

こちらのエラーは19行目で発生しているのかなと思います。
result.firstはnilを返す可能性があると思いますが、
それを!で強制的に参照しようとしています。

ifでnilの判断をするべきなのは、result.firstになると思いました。


イメージとしては以下の画像の通りで、値が入力されていない日は無視して、値が入力されている日のデータのみを折れ線グラフで繋ぐイメージです。

折れ線グラフで表示するのですね。
Chartsに詳しくないのですが、
x軸は、y軸に値があるものだけ設定すれば良いのではないかという気がしてきました。

ちょっとChartsの環境を設定して手元でも再現確認してみようと思います。
確認できたらまた回答を修正しますね。
しばらくお待ちください。

投稿2023/03/29 12:00

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

miyuki

2023/03/29 13:18 編集

わざわざご丁寧にありがとうございます!非常に助かります。。 >ifでnilの判断をするべきなのは、result.firstになると思いました。 if result.first != nilとしたところエラーが解消され、配列に適切な値が入りました!ありがとうございます。
miyuki

2023/03/29 15:14

>x軸は、y軸に値があるものだけ設定すれば良いのではないかという気がしてきました。 ご教授いただきました通り、X軸にはY軸に値があるもののみを設定するという方法で下記のURLを参考に作り替えてみたところ、うまくいきました!アドバイスいただけたおかげで解決できました。ありがとうございます。 https://medium.com/@skipadu/using-realm-and-charts-with-swift-3-in-ios-10-40c42e3838c0
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問