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

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

新規登録して質問してみよう
ただいま回答率
85.37%
Core Data

Core DataはAppleのOS X and iOSのためのオブジェクトモデリングと持続性を持ったフレームワークです。Xcodeはエンティティー、属性そして関係性を特定するためのオブジェクトモデルの編集機能を提供します。

Swift

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

Q&A

解決済

1回答

1335閲覧

PersistenceControllerの初期値

ruru313245

総合スコア8

Core Data

Core DataはAppleのOS X and iOSのためのオブジェクトモデリングと持続性を持ったフレームワークです。Xcodeはエンティティー、属性そして関係性を特定するためのオブジェクトモデルの編集機能を提供します。

Swift

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

0グッド

0クリップ

投稿2023/03/29 01:40

編集2023/04/01 05:44

実現したいこと

CoreDataを用いたList表示

前提

EntityでtextsをBinary Dataで設定、textを Stringで設定しています。

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

Referencing subscript 'subscript(dynamicMember:)' requires wrapper 'Binding<FetchRequest<Item>.Configuration>'

該当のソースコード

SwiftUI

1 2struct ContentView: View { 3 @Environment(\.managedObjectContext) private var viewContext 4 5 @FetchRequest( 6 sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)], 7 animation: .default) 8 private var items: FetchedResults<Item> 9 10 var body: some View { 11 NavigationView { 12 List { 13 ForEach(items) { item in 14 NavigationLink { 15 AnotherView(textEditorText: Text(item.texts[index]) 16 } label: { 17 Text(item.text ?? "") 18 } 19 } 20 .onDelete(perform: deleteItems) 21 } 22 } 23 } 24 Text("Select an item") 25 } 26 } 27} 28 29- 30 31struct AnotherView: View { 32@State var textEditorText = "" 33var body: some View { 34TextEditor(text: $textEditorText).frame(width: .infinity, height: .infinity) 35.toolbar { ToolbarItem(placement: .bottomBar){ Button(action: {additem()}) {Image(systemName: "heart")}} } 36}} 37 38func additem () { 39withAnimation { 40 let newItem = Item(context: viewContext) 41Item.texts.append(textEditorText) 42 43 do { 44 try viewContext.save() 45 } catch { 46 let nsError = error as NSError 47 fatalError("Unresolved error \(nsError), \(nsError.userInfo)") 48 } 49 } 50 }} 51

試したこと

itemをItem、items、にもしました。
indexもとりました。

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

Xcode14.1

追記

新しく立てようと思いましたが、

わかりやすいようにここにしました。

ToolbarItem {
NavigationLink {
AnotherAnotherView(item: Item)
} label: {
Image(systemName: "heart")
}
}


struct AnotherAnotherView: View {

@Environment(\.managedObjectContext) private var viewContext @State var textEditorText = "" var item: Item

var body: some View {
TextEditor(text: $textEditorText).frame(width: .infinity, height: .infinity)

.toolbar { ToolbarItem(placement: .navigationBarLeading){ Button(action: {additem()}) {Image(systemName: "heart")}} }
}

func additem () {
withAnimation {
item.text = textEditorText

do { try viewContext.save() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } }}

とすると、

Cannot convert value of type 'Item.Type' to expected argument type 'Item'

のエラーが出てしまいます。

ListのNavigationLinkでは

NavigationLink {
AnotherAnotherView(item: Item)
} label: {
Text(item.text ?? "")
}

で遷移するのですが、何がちがうのでしょうか

itemとItemの大文字 小文字がみづらくて、すみません

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2023/03/29 05:39

`items.texts[index]` は、 `item.texts` になると思います。 ForEachでループしながら要素をitemで参照しているのかなと思いますので、 item.textsでも大丈夫だと思います。 ループしないでコレクションの要素を参照する場合はリンク先にあるように`[]`(subscripts)を使います。 (大変かもしれませんが、翻訳しながら読んでみてください) https://docs.swift.org/swift-book/documentation/the-swift-programming-language/subscripts/ `Text()`はData型を受け付けませんので、textsを渡してもまだエラーになると思います。 「該当のソースコード」からだけではどうしたいのかわからないので、質問を編集してもらえると助かります。 AnotherViewではText型を受け取っているようですが、これをどのように使っているのでしょうか? なぜtextsはBinary Dataなのでしょうか? --- 厳しいことを書いてしまいますが、ごめんなさい。 過去の質問を見ますと、同じような内容を解決済みにしないまま、新しい質問をしているようですね。 あまり印象が良くなく、回答する人がいなくなってしまうのではないかと思いました。 一つの質問をちゃんと解決済みにしてから新しい質問をした方が良いと思いました。
ruru313245

2023/03/29 05:59

適切なご回答ありがとうございます。 単的にいうとtextsは配列で、AnotherViewにTextEditorがあるのでそこにtextsのStringを入れて編集して再度textsに保存したいと思っています。 Binary Dataである理由は、配列はBinary Data型だと検索して出てきたためです。
ruru313245

2023/03/29 06:05

質問も編集しておきます。
退会済みユーザー

退会済みユーザー

2023/03/29 06:28

コメントありがとうございます。 そうだったのですね。 「texts」という複数形から想像すれば配列ということが読み取れましたね、すみません。 質問欄の編集もありがとうございます。 AnotherViewにつきまして、 textsがStringの配列ということでしたので、 複数のTextEditorを配置しているのかと思ったのですが、 1つなのですね。 AnotherView.additemメソッドにつきまして、 新しく要素を作成する感じになるのでしょうか? 既存のデータを変更するための画面なのかな?と思っていたのですが、そうじゃないみたいですね。 ちょっと手元の環境で再現確認してみたいと思いますので、しばらくお待ちください。 --- また、余計なことを書いてしまいます。ごめんなさい。 どちらが良いかはまた別の検討が必要になってしまいますが、 Core DataにはRelationshipsというものがあるみたいです。 ItemのEntityが1に対して、AnotherViewで扱う文字列のEntityを多、の関係(1:多)に設定すればBinary Dataのような特殊なことをしなくても実現できるかなと思いました。 https://developer.apple.com/documentation/coredata/modeling_data/configuring_relationships Relationshipsはまた別の手間もあると思いますので、 現在のままでOKとは思います。 混乱してしまうようでしたら忘れてください。
ruru313245

2023/03/29 06:46

ありがとうございます。 AnotherView.addItemはAnotherViewのTextEditorの内容をtextsに追加できればいいです。 簡単なメモアプリだと思ってください。 CoreDataを使わないと一連の行程は可能なのですが、CoreDataを使う際に記述が変わって、追加できなくなってしまいました。
退会済みユーザー

退会済みユーザー

2023/03/29 07:00

やっぱりtextsは配列ではなく、通常のStringのような気がしました。 例えば、1回目にAnotherViewを表示した際に、「これは1行目です。」が表示されていたとします。 これを変更して「これは1行目です。(改行)これは2行目です。」と入力して保存したとします。 textEditorTextを配列に追加してしまうと、次のような結果になると思います。 インデックス0: "これは1行目です。" インデックス1: "これは1行目です。(改行)これは2行目です。" 「これは1行目です。」の部分が重複してしまうと思いました。 そうではなく、textsを通常のStringにして、 "これは1行目です。(改行)これは2行目です。"の内容が保持されているtextEditorTextを そのままtextsにStringとして保存すれば良いのではないかと思いました。 あるいは、textsは履歴なのでしょうか?
ruru313245

2023/03/29 07:07

ありがとうございます。 textsは内容の編集が可能な配列です。 上書きができればそれでいいです。 ご提示していただいたとおりtextsにStringとして保存できればいいです。
ruru313245

2023/03/30 07:04

追記していただきありがとうございます textsに関しては本来memoで、textとの区別がつきにくいのと、こちらも言葉足りずでした その後、TextEditorのViewへの遷移はできるようになったのですが、textEditorTextへの文字の代入(とそれに伴う保存)だけが いただいた様にしても init(item: Item) { self.item = item self.textEditorText = item.text ?? "" } としても できません つくづくインスタンス化と値の渡し方のむずかしさを感じています 追記していただけるのは、ありがたいのですが、 ご自身の都合に支障をきたさないようになさってください。 いつもありがとうございます
退会済みユーザー

退会済みユーザー

2023/03/30 08:39

コメントありがとうございます。 > textsに関しては本来memoで、textとの区別がつきにくいのと、こちらも言葉足りずでした ご説明ありがとうございます。 承知いたしました。 --- > textEditorTextへの文字の代入(とそれに伴う保存)だけが > いただいた様にしても > 〜としても できません ちゃんと理解できていなくてすみません。 そういうことだったのですね。 textEditorTextは@Stateのプロパティラッパー型で定義していますよね。 これをinit(イニシャライザ)で初期値を設定するのは、ちょっと特殊な書き方をする必要があるみたいです。 `self.textEditorText` のように参照するのではなく、 `_textEditorText` のように参照するみたいです。 プロパティ名の先頭に「_」をつけたものです。 そして設定する値は `item.text ?? ""` ではなく、 `State(initialValue: item.texts ?? "")` のようになります。 State構造体のイニシャライザを呼び出す形です。 [init(initialValue:)](https://developer.apple.com/documentation/swiftui/state/init(initialvalue:)) まとめると、 回答欄のコードにある通りですが、 次のようになります。 ```swift @State var textEditorText = "" // 省略 init(item: Item) { _textEditorText = State(initialValue: item.texts ?? "") self.item = item } ``` *これに関する公式のドキュメントを見たことがないのですが、stackoverflowなどで見て、そういうものだと思っています。 https://stackoverflow.com/questions/58758370/how-could-i-initialize-the-state-variable-in-the-init-function-in-swiftui --- @Stateをイニシャライザで初期化するための実装は上に記載した通りなのですが、 ちょっと現在の実際の実装の影響もあると思いましたので、 これはまた別の質問として挙げてもらった方が良い気がしました。 AnotherViewを現在の形に沿ったものにして改めて質問してもらえますと幸いです。 --- > 追記していただけるのは、ありがたいのですが、 ご自身の都合に支障をきたさないようになさってください。 ご配慮ありがとうございます。 大丈夫です!
ruru313245

2023/03/30 09:50 編集

丁寧なご返信ありがとうございます。 こちらこそ理解が足りず、すみません。 同じことを説明させてしまいました。 @Stateをそのような書き方をするとは、思いませんでした。 コメントに書くにはもったいない程、丁寧でわかりやすいので、別のところに書かれたほうがいいと思います。 コードのほうは、おかげさまでtextEditorTextへの代入、保存をすることができました。 ありがとうございます。
ruru313245

2023/03/30 22:12

追記していただきありがとうございます
退会済みユーザー

退会済みユーザー

2023/04/01 06:37

> 新しく立てようと思いましたが、 > わかりやすいようにここにしました。 ごめんなさい。 気づきませんでした・・ 別の質問にしてもらった方が良かったかもしれません。 *使ったことはないのですが、私への回答依頼であれば、相互フォローにしてもらって、その状態だと相手に回答依頼を出すことができるみたいです。 > Cannot convert value of type 'Item.Type' to expected argument type 'Item' > のエラーが出てしまいます。 > ListのNavigationLinkでは > 〜で遷移するのですが、何がちがうのでしょうか エラー自体は、Item型のインスタンスを要求している引数のところに、Item型そのものを渡しているから だと思いました。 Listの方は、`ForEach(items) { item in`でitem変数が設定された上で処理されていると思います。 ToolbarItemの方は、参照できるitemがないですよね? 新規で追加したいのでしょうか? ちょっとこの辺りはどうしたいのか設計も含めて把握しないといけないかもしれません。 (やっぱり別の質問にしてもらった方が良いのかなと思いました。) > itemとItemの大文字 小文字がみづらくて、すみません それはOKと思いますよ。 Swiftでは 変数は小文字から始めるのが一般的ですし、 https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics#Declaring-Constants-and-Variables 構造体やクラスは大文字から始めるのが一般的だと思います。 https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures#Definition-Syntax
ruru313245

2023/04/01 07:38

ご回答ありがとうございます。 大丈夫ですよ、あなたひとりに負担をかけないように他の方にも依頼した形にしたので 今までの経緯から、フォローさせていただきますが、わたしが投稿したからといって、かならず返答しないといけないとは、思わないでください。 あなたの予定をくずしてまで、回答はのぞんでいません コードの方は そうですね 別の質問として投稿します
ruru313245

2023/04/01 07:58

参照のリンクもありがとうございます
退会済みユーザー

退会済みユーザー

2023/04/01 08:12

> あなたの予定をくずしてまで、回答はのぞんでいません ありがとうございます。 本当にダメな時は反応しなくなったりすると思いますので、 大丈夫です! > 別の質問として投稿します こちらもありがとうございます。 回答する側としては、すでに「解決済」になっている質問について、 まだ回答を待っているとはあまり思わないですので、 別の質問の方が回答してもらえるかなと思いました。 解決しないまま次から次へと質問を出してしまうことは それはそれで問題があるかなとも思いますが、 明確な問題を挙げた上での質問でしたら、 ちゃんと回答ももらえると思いますし、 それが解決したら、 また別の明確な問題の質問をすれば良いと思いました。 *曖昧でぼやけた問題の質問になってしまうと回答するのも難しくなって、結果的に回答がもらえなくなってしまうと思います。 この辺りは難しくて、回答する側は「ちゃんとした質問しろ!」と思ってしまうところだと思うのですが、 質問する側としては、そこまで具体的な問題点の質問をすることができるレベルなら、 大抵のことは質問するまでもなく自己解決できてしまうことになってしまうと思うんですよね。 (そうするとこのような質問回答をする場所って必要なのかな?と思ったりします) (お互い相手を思って理解しようとすることは必要ですよね)
ruru313245

2023/04/01 08:59

おっしゃる通りだと思います
ruru313245

2023/04/01 09:03

根本的にそこでした ありがとうございます
guest

回答1

0

ベストアンサー

質問欄の修正などありがとうございます。

サンプルのコードを書いてみました。
いかがでしょうか。
(変更したポイントにコメントを書いていますので、そちらも読んでみてください)

swift

1import SwiftUI 2import CoreData 3 4struct ContentView: View { 5 @Environment(\.managedObjectContext) private var viewContext 6 7 @FetchRequest( 8 sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)], 9 animation: .default) 10 private var items: FetchedResults<Item> 11 12 var body: some View { 13 NavigationView { 14 List { 15 ForEach(items) { item in 16 NavigationLink { 17 // itemを渡すように変更しました。 18 AnotherView(item: item) 19 } label: { 20 Text(item.text ?? "") 21 } 22 } 23 .onDelete(perform: deleteItems) 24 } 25 // テスト用のitemを追加するためのツールバーを用意しました。 26 .toolbar { 27 ToolbarItem { 28 Button(action: addItem) { 29 Label("Add Item", systemImage: "plus") 30 } 31 } 32 } 33 Text("Select an item") 34 } 35 } 36 // テストのために要素を追加するメソッドを用意しました。 37 private func addItem() { 38 withAnimation { 39 let newItem = Item(context: viewContext) 40 // EntityにtimestampというDate型のAttributeを残したままなので設定しています。 41 newItem.timestamp = Date() 42 newItem.text = itemFormatter.string(from: newItem.timestamp!) 43 } 44 } 45 // 該当のソースコードにdeleteItemsがなかったため空のメソッドを記述しました。 46 private func deleteItems(offsets: IndexSet) { 47 } 48} 49 50struct AnotherView: View { 51 @Environment(\.managedObjectContext) private var viewContext 52 // *** 独自のBackボタン実装時に戻るためのプロパティを追加しました。 53 @Environment(\.dismiss) private var dismiss 54 @State var textEditorText = "" 55 // itemを受け取るように追加しました。 56 let item: Item 57 var body: some View { 58 TextEditor(text: $textEditorText) 59 // 警告が出ていたためmaxWidth,maxHeightに変更しました。 60 .frame(maxWidth: .infinity, maxHeight: .infinity) 61 // *** 独自のBackボタンを実装するため標準のBackボタンを非表示にしました。 62 .navigationBarBackButtonHidden(true) 63 .toolbar { 64 // 手元の環境だと.bottomBarではボタンが表示されなかったためナビゲーションバーに変更して確認しました。 65 ToolbarItem(placement: .bottomBar) { 66 Button(action: additem) { 67 Image(systemName: "heart") 68 } 69 } 70 // *** 独自のBackボタンを追加しました。 71 ToolbarItem(placement: .navigationBarLeading) { 72 Button(action: back) { 73 Text("Back") 74 } 75 } 76 } 77 } 78 // itemを受け取ってtextEditorTextの初期値を設定するためのイニシャライザを追加しました。 79 init(item: Item) { 80 _textEditorText = State(initialValue: item.texts ?? "") 81 self.item = item 82 } 83 private func additem() { 84 withAnimation { 85 // item.textsを変更して保存するように変更しました。 86 item.texts = textEditorText 87 do { 88 try viewContext.save() 89 } catch { 90 let nsError = error as NSError 91 fatalError("Unresolved error \(nsError), \(nsError.userInfo)") 92 } 93 } 94 } 95 // *** Backボタンのメソッドを追加しました。 96 private func back() { 97 additem() 98 dismiss() 99 } 100} 101 102private let itemFormatter: DateFormatter = { 103 let formatter = DateFormatter() 104 formatter.dateStyle = .short 105 formatter.timeStyle = .medium 106 return formatter 107}()

追記

「戻るときの保存」のコメントを受けてコードを修正しました。
// *** のようなコメントが修正ポイントです。

追記2

コメントありがとうございます。
もう不要かもしれませんが追記です。

「セルの中身」はtextsのvalueです

すみませんでした。理解したかもしれません。
itemにはtextとtextsの2つのプロパティがあって、
ContentViewのリスト(セル)に表示するのはtextなのだと思っていました。
(textはどこから設定するのだろう?とも思いました・・)
ここにはitem.textsが表示されるべきなのですね。

セルに表示される部分は、NavigationLinkのlabel引数で指定していますので、
21行目の Text(item.text ?? "") は、
Text(item.texts ?? "") になるのかなと思います。
init(destination🏷️)

長い文字列などはそのまま表示されてしまうと思いますので、
.frameモディファイアで、maxHeight,alignmentなどを指定してあげると良いのかなと思います。
frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:)

追記3

解決済みですが、
コメントいただきましたので、
同じ内容を回答欄にも記載しておきますね。

textEditorTextへの文字の代入(とそれに伴う保存)だけが
いただいた様にしても
〜としても できません

textEditorTextは@Stateのプロパティラッパー型で定義していますよね。
これをinit(イニシャライザ)で、初期値を設定するのは、ちょっと特殊な書き方をする必要があるみたいです。

self.textEditorText のように参照するのではなく、
_textEditorText のように参照するみたいです。
プロパティ名の先頭に「_」をつけたものです。

そして設定する値は
item.text ?? "" ではなく、
State(initialValue: item.text ?? "") のようになります。
State構造体のイニシャライザを呼び出す形です。
init(initialValue:)

まとめると、
回答欄のコードにある通りですが、
次のようになります。

swift

1@State var textEditorText = "" 2// 省略 3init(item: Item) { 4 _textEditorText = State(initialValue: item.text ?? "") 5}

*これに関する公式のドキュメントを見たことがないのですが、stackoverflowなどで見て、そういうものだと思っています。
https://stackoverflow.com/questions/58758370/how-could-i-initialize-the-state-variable-in-the-init-function-in-swiftui

投稿2023/03/29 07:46

編集2023/03/30 14:25
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ruru313245

2023/03/29 08:14

ありがとうございます。 とても参考になります。 一点だけ、item.texts = textEditorText で Cannot assign value of type 'String' to type 'Data?' というエラーがでてしまいます 解消できますか? … textsをStringにすることで解消できました。すみません。 その後、 セルのタップでTextEditorに遷移することはできました。 しかし、 セルの中身の代入、 戻るときの保存 ができませんでした。 ご確認をお願いいたします。
ruru313245

2023/03/29 08:16

余計なお世話かもしれませんが、 数日前タイムラインで志望動機の投稿をみました。 わたし個人としては、3つともよく書けていてあとは提出して面接を受けるだけなのかな と思いました。 技術もしっかりしていて、受け答えも丁寧なのでその感じで当日も臨めばよいとおもいます。 ps プレイヤーとしてコメントさせていただくと、わたしも区切るとき--- をよくつかうのでaffinityを感じました。 がんばってください
ruru313245

2023/03/29 08:28

先述の理由により、お忙しいところ 長コードありがとうございました。 あとは自分でやってみます
退会済みユーザー

退会済みユーザー

2023/03/29 08:53

> Cannot assign value of type 'String' to type 'Data?' > textsをStringにすることで解消できました。すみません。 すみません、textsはBinary DataからStringに変更していました。 > セルの中身の代入、 > 戻るときの保存 戻るときの保存はBackボタンですね。 ちょっとこれから回答を修正してみます。 bottomBarのボタンで保存するみたいでしたので、Backボタンタップ時は何もしないのかと思ってしまいました。 「セルの中身の代入、」はちょっと正しく解釈できませんでしたので、 またコメントもらえますと幸いです。 --- タイムラインはどこのですか? 余計なお世話ではないです。 ありがとうございます。 affinityとか難しい英語を使うのですね。 親近感とか訳せば良いのですかね。 嬉しいです。
ruru313245

2023/03/29 12:58 編集

それは良かったです 丁寧で迅速な対応 ありがとうございました 「セルの中身」はtextsのvalueです コードの追記修正もありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問