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

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

新規登録して質問してみよう
ただいま回答率
85.44%
データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Swift

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

Q&A

1回答

178閲覧

SwiftUI+SwiftDataで親子関係にある階層構造のデータをINSERTしたいです。

takopu

総合スコア0

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Swift

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

0グッド

0クリップ

投稿2024/05/16 05:33

編集2024/05/16 05:55

実現したいこと

ビューに配置した「Add」ボタンを押した際に1対多の親子構造のデータをSwiftDataにINSERTしたいと思います。
親データは日付と気温を入力し、子データの入力項目は、入力定義データを読み込んでビュー表示時に入力欄を生成します。
ソース上では配列「arr」にしています。

発生している問題・分からないこと

Parentに子データの配列「children」を渡そうとするとParentにセットできないでエラーになります。
そもそものアプローチの仕方が間違っているのでしょうか?

該当のソースコード

swift

1//親子のデータ構造モデル 2import Foundation 3import SwiftData 4 5@Model 6final class Parent { 7 @Attribute(.unique) var pid: UUID 8 var hiduke: Date 9 var kion: String 10 var create_date: Date 11 var children: [Child] = [] 12 @Relationship(deleteRule: .cascade, inverse: \Child.parent) 13 init(hiduke: Date, kion: String, children: [Child]) { 14 self.pid = UUID() 15 self.hiduke = hiduke 16 self.kion = kion 17 self.create_date = Date() 18 self.children = children 19 } 20} 21 22 23@Model 24final class Child { 25 var dataid: Int 26 var name: String = "" 27 var create_date: Date 28 var parent: Parent? 29 30 init(dataid: Int, name: String, parent: Parent){ 31 self.dataid = dataid 32 self.name = name 33 self.parent = parent 34 self.create_date = Date() 35 } 36 37}

swift

1//ビュー 2import SwiftUI 3import SwiftData 4 5struct EntryView: View { 6 @Environment(\.modelContext) private var modelContext 7 @State private var txtKion: String = "" 8 @State private var txtHiduke: Date = Date() 9 10 @State var children:[Child] = [] //←Parentに紐付く子データ 11 var oya:Parent = Parent(hiduke: Date(), kion: "", children: []) 12 13 private func appendChild(ko: Child) -> Bool { 14 children.append(ko) 15 return true 16 } 17 18 let arr = ["入力項目1", "入力項目2", "入力項目3"] 19 20 var body: some View { 21 VStack{ 22 DatePicker(selection: $txtHiduke, displayedComponents:[.date], label: { Text("日付") }) 23 .padding(.all) 24 .environment(\.locale, Locale(identifier: "ja_JP")) 25 26 TextField("気温", text: $txtKion) 27 28 ForEach(arr, id:\.self) { item in 29 HStack{ 30 var ko = Child(dataid: 1, name: "", parent: oya) 31 32 Text(item) 33 ChildView(entity: ko) 34 .onAppear(){ 35 let x = appendChild(ko: ko) 36 } 37 } 38 } 39 40 41 Button("Add") { 42 let newItem = Parent(hiduke: txtHiduke, kion: txtKion, children: children) //←エラー発生個所 43 modelContext.insert(newItem) 44 } 45 } 46 } 47}

swift

1//子データの入力欄用ビュー 2import SwiftUI 3struct ChildView: View { 4 5 let entity: Child 6 7 @State private var questionVariable = "" 8 9 var body: some View { 10 11 TextField(entity.name, text: $questionVariable) 12 .onChange(of: questionVariable) { 13 entity.name = questionVariable 14 15 16 } 17 } 18}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

親子構造のデータを扱えることは分かりましたが、具体的な例が見当たりませんでした。

補足

特になし

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

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

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

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

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

guest

回答1

0

Parentにセットできないでエラーになります。

エラーメッセージもそのまま記載すると良いかもしれませんね。

公式のドキュメントを探す余裕がなくて、
個人の方のページを引用します。すみません。

ポイントはコードのコメントに記載した「// ----」のようなコメントになるかなと思いました。

swift

1@Model 2final class ExplicitOneToManyItem { 3 4 @Attribute(.unique) 5 var id: Int 6 7 // --- 属性はchildrenプロパティの上に記述した方が良さそうかなと思いました。 8 @Relationship(inverse: \ChildExplicitOneToManyItem.parent) 9 var children: [ChildExplicitOneToManyItem] = [] 10 11 init(id: Int, children: [ChildExplicitOneToManyItem] = []) { 12 self.id = id 13 self.children = children 14 } 15} 16 17@Model 18final class ChildExplicitOneToManyItem { 19 20 @Attribute(.unique) 21 var id: Int 22 23 var parent: ExplicitOneToManyItem? 24 25 // --- parentはイニシャライザの引数で受けていません。明示的にparentプロパティを設定していません。(SwiftDataの仕組みによって自動的にparentが設定される?) 26 init(id: Int) { 27 self.id = id 28 } 29}

SwiftData 入門


下のようなテストコードでparentとchildが参照できました。

swift

1 @Query private var parentCollection: [Parent] 2 func action() { 3 for parent in parentCollection { 4 print("\(parent.create_date), \(parent.children.count)") 5 for child in parent.children { 6 print("\(child.parent?.kion ?? "nil")") 7 } 8 } 9 }

投稿2024/05/16 11:35

yametai

総合スコア80

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

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

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

ただいまの回答率
85.44%

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

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

質問する

関連した質問