Realmに連続してデータを追加する
解決済
回答 3
投稿
- 評価
- クリップ 0
- VIEW 2,573
前提・実現したいこと
配列を引数に渡してfor文で配列の中にある全データをRealmに保存したいです。
発生している問題・エラーメッセージ
一番最後の値のみ追加される
該当のソースコード
import Foundation
import RealmSwift
@objcMembers class DayScheduled: Object {
dynamic var date = String()
dynamic var plans = List<OneDayScheduled>()
// dateをプライマリキーに設定
override static func primaryKey() -> String? {
return "date"
}
}
@objcMembers class OneDayScheduled: Object {
dynamic var title = String()
dynamic var places = List<OneDayScheduledPlace>()
// titleをプライマリキーに設定
override static func primaryKey() -> String? {
return "title"
}
}
@objcMembers class OneDayScheduledPlace: Object {
dynamic var place = String()
}
import Foundation
import RealmSwift
class RealmSys {
// Scheduled追加(idから)
func addScheduled(date: String = "", title: String = "", places: [String] = []) {
Realm.Configuration.defaultConfiguration = config
let dayscheduled:DayScheduled = DayScheduled()
let onedayscheduled:OneDayScheduled = OneDayScheduled()
let onedayscheduledplace:OneDayScheduledPlace = OneDayScheduledPlace()
try! realm.write {
if date != "" {
dayscheduled.date = date
}
if title != "" {
onedayscheduled.title = title
}
if !places.isEmpty {
for place in places {
onedayscheduledplace.place = place
onedayscheduled.places.append(onedayscheduledplace)
realm.add(onedayscheduled, update: true)
}
}
dayscheduled.plans.append(onedayscheduled)
realm.add(dayscheduled, update: true)
}
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
check解決した方法
0
下記のようにfor文で一回一回初期化したら狙った結果になりました。
import Foundation
import RealmSwift
class RealmSys {
// Scheduled追加(idから)
func addScheduled(date: String = "", title: String = "", places: [String] = []) {
Realm.Configuration.defaultConfiguration = config
let dayscheduled:DayScheduled = DayScheduled()
let onedayscheduled:OneDayScheduled = OneDayScheduled()
//↓こっちは削除
//let onedayscheduledplace:OneDayScheduledPlace = OneDayScheduledPlace()
try! realm.write {
if date != "" {
dayscheduled.date = date
}
if title != "" {
onedayscheduled.title = title
}
if !places.isEmpty {
for place in places {
//↓こっちに追加
let onedayscheduledplace:OneDayScheduledPlace = OneDayScheduledPlace()
onedayscheduledplace.place = place
onedayscheduled.places.append(onedayscheduledplace)
realm.add(onedayscheduled, update: true)
}
}
dayscheduled.plans.append(onedayscheduled)
realm.add(dayscheduled, update: true)
}
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
デバックを自分でしてみて、確認してみてはどうでしょうか。
そうすれば、今後もエラーが出た際に自分で解決できるようになると思います。
簡単なことをミスってるだけかもしれませんし。
print("placesには", places.count, "個データがあります。") // ※
for place in places {
print("placeは", place, "です。")
onedayscheduledplace.place = place
onedayscheduled.places.append(onedayscheduledplace)
realm.add(onedayscheduled, update: true)
print("onedayscheduledは", onedayscheduled)
print("dayscheduled.plansは", dayscheduled.plans)
}
とすれば、どのタイミングで何が、どう動いてるのか、自分でわかると思います。
printは便利なので、ぜひ使いこなせるようなるといいとお思います。
と書いたところで、気づいたのですが、各onedayscheduledのみforで回してて、
肝心のdayscheduled.plansがfor文の外なので、
最後の1回しか登録されないんだと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
そのConsoleの様子だと、
forを回すごとに、登録はできている
(Placesの個数がちゃんと増えている)
しかし、毎回、Placesの要素であるplaceが最後の要素に置き換えられている
ということがわかります。
forの回し方に問題がありそうだなと思って、
詳細にコードを見させていただいたところ、、、
実は、Realm Objectの作成の仕方に問題があることに気づきました。
OneDayScheduledPlaceはplacesの個数分作成しないといけませんよね?
ということは毎回新たなOneDayScheduledPlaceを作成しないといけません。
最初にlet onedayscheduledplace:OneDayScheduledPlace = OneDayScheduledPlace()
で 1個しか作ってないところは間違いになります。
また、DaysScheduledのdateはPrimary Keyに設定されてるので、重複はダメということになります。
つまり毎回先に登録されていないか検索する必要が出てきます。
そして、存在すれば、それをセット、なければ新規作成することになります。
そこを踏まえ書くと、
class RealmSys {
// Scheduled追加(idから)
func addScheduled(date: String = "", title: String = "", places: [String] = []) {
if date == "" || title == "" || places.count == 0 {
return
} else {
Realm.Configuration.defaultConfiguration = config
// まず全体から入力日付と同じ日の存在を検索し、一致するデータをセット
let sameDay = NSPredicate(format: "date = %@", date)
let matchedDayScheduled = realm.objects(DayScheduled.self).filter(sameDay)
// 変数でDayScheduledを作成し重複あれば、過去のをセットする
var cDayScheduled:DayScheduled = DayScheduled()
if matchedDayScheduled.count > 0 {
print("Matched data exists.")
cDayScheduled = matchedDayScheduled.first // 複数ないけど、1個目を指定…記述上必要
}
let onedayscheduled = OneDayScheduled()
try! realm.write {
// まずonedaysscheduledplaceを作成
for place in places {
print("Place is:", place)
let onedayscheduledplace:OneDayScheduledPlace = OneDayScheduledPlace()
onedayscheduledplace.place = place
realm.add(onedayscheduledPlace)
onedayscheduled.places.append(onedayscheduledplace)
print("Added onedaysscheduledplace:", onedayscheduledplace)
}
onedayscheduled.title = title
realm.add(onedayscheduled, update: true)
print("Added OneDayScheduled:", onedayscheduled)
cDayScheduled.date = date
cDayScheduled.plans.append(onedayscheduled)
realm.add(cDayScheduled, update: true)
print("Total cDayScheduled:", cDayScheuled)
}
}
}
}
これで大丈夫だと思います。
printで各所でコンソール出力も入れているので試して見てください。
スペルミスはあるかもしれませんが、その際はご容赦ください。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2018/06/01 00:54 編集
重複check機能が必要になります。
また、onedayshceduledplaceはデータベースに登録されていませんが。。。
それはそれでいいのでしょうか?
さらに、余計かもしれませんが、日付はStringで保存せず、
Date型にした方が他のクラスを使いやすくないですか?
自前で入力checkや並び替え、月に条件を絞った検索など実現に
一手間増える事になってしまいそうです。
また、エラーを避ける意味でも、
ない日付をアラートするとかの実装も結構な手間になりそうです。
(String→Date型に変換するからいいよって言えば、それまでですが、、、)
そして、dateとdateのように変数や定数に同じ文字列を使うと
どっちがどっちを表しているのかわかりづらいので、
c_date(current)やr_date(received)、何でもいいんですが
分けた方が見直す時に見やすいし、検索もかけやすいので
利点があると思います。
最後に配列チェックも登録する際にはねればいいかもしれませんが、
["", "", ""]のような空白の配列もisEmptyや.count == 0ではスルーしてしまいますので、
追加コードが必要になります。考えてみて下さい。
口うるさくすいませんでした、、、
それではお互いいいアプリ作れるように頑張りましょう。