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

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

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

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

Swift

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

Q&A

解決済

3回答

768閲覧

カスタムViewの表示

ruru313245

総合スコア8

Core Data

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

Swift

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

0グッド

0クリップ

投稿2023/04/02 10:18

編集2023/04/03 09:36

実現したいこと

タップしたら、その中の配列(プロパティ)を表示したいです

前提

FolderRowとして、カスタムViewセルをstructしています。

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

Cannot find 'folderRowArray' in scope - Extraneous whitespace after '.' is not permitted --- Missing arguments for parameters 'folderRowArray', 'folderRowSystemNameText', 'folderRowName' in call

該当のソースコード

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 private let list1 = [ 11 SampleStruct(sectionTitle: "A", listContent: ["elementA1", "elementA2", "elementA3"]), 12 SampleStruct(sectionTitle: "B", listContent: ["elementB1", "elementB2", "elementB3"]), 13 SampleStruct(sectionTitle: "C", listContent: ["elementC1", "elementC2", "elementC3"]), 14 ] 15 16 var body: some View { 17 NavigationView { 18 List { 19 ForEach(list1) { item in 20 Section(item.sectionTitle) { 21 ForEach(item.listContent, id: \.self) { item2 in 22 Text(item2)} 23 .toolbar { 24 ToolbarItem(placement: .navigationBarTrailing) { 25 EditButton() 26 } 27 } 28 } 29 } 30 } 31 .navigationTitle("A") 32 }}} 33 34struct FolderRow: View { 35 var folderRowArray: [String] 36 var systemNameText: String 37 var folderRowName: String 38 var body: some View { 39HStack{ 40Image(systemName: systemNameText) 41Text(folderRowName) 42Text("\(folderRowArray.count)") 43} 44 } 45} 46 47 struct SampleStruct : Identifiable { 48 let id = UUID() 49 let sectionTitle: String 50 let listContent: [String] 51 } 52 53 struct ContentView_Previews: PreviewProvider { 54 static var previews: some View { 55 ContentView() 56 } 57 } 58

試したこと

とてもややこしいのが、遷移したいのは、FolderRowの中のfolderRowArrayなので、folderRow.folderRowArrayとするのか、あるいはitemをからめて記述するのか、というところです。

(folderRowArrayもitemに保存するはずですので)

両方試しました。

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

Xcode14.1

追記

![イメージ説明]
イメージ説明

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2023/04/03 08:58

コメントありがとうございます。 修正できそうですか? > 意としてるのは、iPhoneのメモの追加フォルダです なるほど。 固定と言っていたと思うのですが、 フォルダ自体は増えたり減ったりしないということですかね。 (ユーザーがフォルダを追加したり、削除したりはできない?) そうだとすると、 フォルダの表示の部分(ビュー・画面の構造体)は、 ForEachなどは使わずに、 直接Sectionを3つ("A","B","C")と続けて記述しても良いのかもしれませんね。 > あとから追加してるにもかかわらず、そのそれぞれをタップすると、そのそれぞれの配列に遷移します ごめんなさい。 ここはまだちゃんと理解できないです・・ 画面設計書とかワイヤーフレームとかイメージを共有できていれば、また違うのかもしれませんが、 ちょっと言葉だけでは伝えるのも、理解するのも、難しいところですね。 (システム開発{アプリ開発}の難しいところですね) > プレビューコントローラーにもfolderRowへの言及の必要が書かれ、そんなこと通常であり得るの?という心情です。 構造体の場合はプロパティを定義すると 自動的にイニシャライザでそれを受け取るようになっているみたいですね。 (「Memberwise Initializers」というみたいです) Memberwise Initializers for Structure Types https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization#Memberwise-Initializers-for-Structure-Types ContentViewに`var folderRow: FolderRow`と記述してしまっていますので、 FolderRowの構造体を受け取るようなイニシャライザが自動的に実装されることになると思います。 --- ちょっとこの質問とは直接的には関係ないですが、 1つお聞きしておきたいことがあります。 フォルダごとにデータを管理すると思いますが、 このデータはどのように識別しますでしょうか? ItemのEntityにいくつかAttributeを追加されていたようですが、 フォルダ名など追加する予定でしょうか? *見当違いなことを聞いてしまっていたらすみません
ruru313245

2023/04/03 09:24

コメントありがとうございます ちょうど更新しようと思っていたところなのですが 考えている方法がデジタルだとしたら、それができずにアナログでやろうとしてむだにおなじstructがふえていきそうだったので、 そのことについてコメントしようとおもっていました --- リレーションでは?と思い、調べていたのですが、 そうしなくても、いける気がしています --- ItemのattributeはひとつのEntityにまとめて と思いましたが、ひとつのセルが持つBoolなどを第二のEntityに保存して、リレーションかな…?ともおもっています (先述とことなっています) --- 自動でイニシャライザを記述ということは、やはりプレビュープロバイダーにもfolderRowのプロパティの記述が必須なのですね --- 固定の3つのうちのひとつ(のセクション)には、あとから追加することになります。 初期段階から、3つとも名前など全て固定です
ruru313245

2023/04/03 09:38

クラッシュするコードだったので、ひとつ前のコードにしました
ruru313245

2023/04/03 09:41

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

退会済みユーザー

2023/04/03 11:06

> むだにおなじstructがふえていきそうだったので、 正しく理解できていないかもしれませんが、 レイアウトが同じであれば、 ビュー(画面)のstructを1つ作って、 データだけを親から渡してあげれば良いのかなと思います。 --- > ItemのattributeはひとつのEntityにまとめて と思いましたが、ひとつのセルが持つBoolなどを第二のEntityに保存して、リレーションかな…? 承知しました。 引き続き検討してみてください。 CoreDataはあまり詳しくないのですが、 データベース設計としては、 同じまとまりなら一つのEntityで良いのではないかなと思います。 1:多の関係になるのでしたら、リレーションシップになる感じですかね。 (考え方は色々あると思いますので、話半分で聞いてOKです) --- > 自動でイニシャライザを記述ということは、やはりプレビュープロバイダーにもfolderRowのプロパティの記述が必須なのですね こちらは、解釈が逆になるかなと思います。 ContentViewに`var folderRow: FolderRow`と記述してしまうと、 自動的にfolderRowを引数に受け取るようになってしまうので、 ContentViewを呼び出す側で`ContentView(folderRow: ~)`と記述しないといけないことになってしまいます。 ですので、ContentViewには`var folderRow: FolderRow`を記述しない方針で実装する必要があると思います。 -- > 固定の3つのうちのひとつ(のセクション)には、あとから追加することになります。 セクションの一つもユーザーによって追加する感じなのですね。 (ちょっと余計イメージがわからなくなってしまいましたが・・) --- 画面イメージもありがとうございます。 Editボタンがたくさんになってしまいましたね・・ --- この質問のタイトル「カスタムViewの表示」が目的ですよね。 基本的には前の質問で使っていたのと同じようにすればOKなのですけどね。 (AnotherAnotherViewとかのことです) 現在の質問欄のコードにある`Text(item2)`の部分を、 FolderRowを呼び出すような感じになります。
ruru313245

2023/04/03 11:30

3つの固定セルは、それぞれ用意して、if で表示するEntityのStringを3つにすれば、解決できるのでは?と思っています 親からデータだけ これが理想なのですが、タップ判定ってできるのでしょうか? このセルをタップしたら、このEntityのtext○を表示 のように (text1, text2, text3でattributeを設定します) --- イニシャライザの記述はあまり好ましくないのでfolderRowは ContentViewにはのせません すみません、 iPhoneのフォルダ追加のようなものだとおもってください EditButton()はバグですか? --- できるだけ前回のものを使いたいとおもっています。 あと一点 item2がどこに宣言されているのか、わかりません
ruru313245

2023/04/03 11:39 編集

リレーションかな、とおもっている理由は、ひとつのセルが待つ複数のデータ(String、Bool)をデータごと に保存する必要があるのかな?とおもっているためです
退会済みユーザー

退会済みユーザー

2023/04/03 11:47 編集

> これが理想なのですが、タップ判定ってできるのでしょうか? このセルをタップしたら、このEntityのtext○を表示 のように (text1, text2, text3でattributeを設定します) タップはできると思います。 でも、仕様がうまく把握できませんでした・・ フォルダA、フォルダB、フォルダCに1つのエンティティがそれぞれ表示されることもあるのでしょうか? (データの関係がうまく把握できていないのかもしれません) (フォルダAはtext1?、フォルダBはtext2?、フォルダCはtext3?のような?) > EditButton()はバグですか? ForEachの中にtoolbarを記述しているためですね。 3つ目の回答のコードを参考に、 どこの位置にtoolbarを記述しているか見てみてください。 > item2がどこに宣言されているのか、わかりません item2はクロージャの中で使える引数なのですが、 ForEachに渡しているitem.listContent(Stringの配列)につきまして、 ForEachがStringの配列を1つずつに分けて クロージャの中身({}のことです)を実行してくれます。 この時の要素1つをitem2の変数に設定して実行しれくれる形です。 (宣言がどこかというと、「in」の直前ですね) Closure Expression Syntax https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/#Closure-Expression-Syntax > リレーションかな、とおもっている理由は、ひとつのセルが待つ複数のデータ(String、Bool)をデータごと に保存する必要があるのかな? そうなのですね。 では、1:多の関係っぽいですね。 リレーションシップで良いのかもしれませんね。
ruru313245

2023/04/03 12:24 編集

フォルダAはtext1?、フォルダBはtext2?、フォルダCはtext3?のような? そうです ほかに方法があれば、いいですが ここでのリレーションの話は申しわけないので、やめにします ありがとうございます --- イニシャライザの記述が好ましくない は語弊がありますね プレビュープロバイダーへのその他のViewのイニシャライザの記述は です
ruru313245

2023/04/03 12:26

カスタムViewの表示はText(text)の部分をFolderRowのようなstructとそのプロパティ でいいのですね。
ruru313245

2023/04/03 12:28 編集

EditButton()のForEachの記述もありがとうございます
guest

回答3

0

ベストアンサー

入れ違いでコメントが届いたみたいなのですが、
先にコードを書いておきますね。

質問欄に画像も貼り付けてもらったことで、
少しだけ理解が進みました。

FolderRowの使い方は次のような感じになると思います。

swift

1 2import SwiftUI 3 4struct ContentView: View { 5 var body: some View { 6 NavigationView { 7 List { 8 Section("A") { 9 FolderRow( 10 // --- folderRowArrayはitemsからデータを絞り込んで渡すことになると思いました。 11 folderRowArray: ["1", "2", "3", "4", "5", "6"], 12 systemNameText: "fossil.shell", 13 folderRowName: "フォルダA1") 14 FolderRow( 15 folderRowArray: ["1", "2", "3", "4", "5"], 16 systemNameText: "atom", 17 folderRowName: "フォルダA2") 18 FolderRow( 19 folderRowArray: ["1", "2", "3", "4"], 20 systemNameText: "carrot", 21 folderRowName: "フォルダA3") 22 } 23 Section("B") { 24 FolderRow( 25 folderRowArray: ["1", "2", "3"], 26 systemNameText: "tree.circle", 27 folderRowName: "フォルダB1") 28 FolderRow( 29 folderRowArray: ["1", "2"], 30 systemNameText: "camera.macro.circle", 31 folderRowName: "フォルダB2") 32 } 33 Section("C") { 34 FolderRow( 35 folderRowArray: ["1"], 36 systemNameText: "leaf.circle", 37 folderRowName: "フォルダC1") 38 } 39 } 40 .toolbar { 41 ToolbarItem(placement: .navigationBarTrailing) { 42 EditButton() 43 } 44 } 45 } 46 } 47} 48 49struct FolderRow: View { 50 var folderRowArray: [String] 51 var systemNameText: String 52 var folderRowName: String 53 var body: some View { 54 HStack{ 55 Image(systemName: systemNameText) 56 Text(folderRowName) 57 Text("\(folderRowArray.count)") 58 } 59 } 60} 61 62struct ContentView_Previews: PreviewProvider { 63 static var previews: some View { 64 ContentView() 65 } 66}

投稿2023/04/03 11:34

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ruru313245

2023/04/04 00:16 編集

ベストアンサーにさせていただきましたが、当初意としていたものは、クラッシュするといったこのコードに近いです struct ContentView: View { @Environment(\.managedObjectContext) private var viewContext @FetchRequest( sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: false)], animation: .default) private var items: FetchedResults<Item> var body: some View { NavigationView { List { ForEach(items) { item in NavigationLink { AnotherView(item: item) } label: { Text(item.text ?? "") } } .onDelete(perform: deleteItems) } .toolbar { #if os(iOS) ToolbarItem(placement: .navigationBarTrailing) { EditButton() } #endif if let item1 = items.first { ToolbarItem { NavigationLink { AnotherAnotherView(item: item1) } label: { Image(systemName: "pin") } } } } Text("Select an item") } } private func addItem() { withAnimation { let newItem = Item(context: viewContext) newItem.timestamp = Date() do { try viewContext.save() } catch { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } } private func deleteItems(offsets: IndexSet) { withAnimation { offsets.map { items[$0] }.forEach(viewContext.delete) do { try viewContext.save() } catch { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } } } private let itemFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .short formatter.timeStyle = .medium return formatter }() struct AnotherView: View { @Environment(\.managedObjectContext) private var viewContext @State var textEditorText = "" var item: Item init(item: Item) { _textEditorText = State(initialValue: item.text ?? "") self.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)") } } }} 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)") } } }} struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext) } }
退会済みユーザー

退会済みユーザー

2023/04/04 02:37

回答者からのコメントをここに書くとメールで通知が届かないかもしれませんが、 書き込みしますね。 > ベストアンサーにさせていただきましたが、当初意としていたものは、クラッシュするといったこのコードに近いです そうですよね。 前の質問では、フォルダを考えずitemsの一覧を表示して、編集画面を表示する感じでしたよね。 今回の質問は、主にFolderRowを呼び出す部分に関するものだと思いましたので、 AnotherView、AnotherAnotherViewなどの部分は切り離したコードにしました。 前の質問のビューの構成は次のような感じだと思います。 ContentView (itemsの一覧) __AnotherView __AnotherAnotherView これを今回の質問も踏まえて、フォルダの一覧などのビューを組み込んだ時の構成は次のような感じになると思います。 TopView (フォルダの一覧) __FolderRow (NavigationLinkのlabelに記述する) __ContentView (itemsの一覧)(NavigationLinkのdestinationに記述する) ____AnotherView ____AnotherAnotherView 親のビューから子のビューへ、 データを渡しながら構成していくのが SwiftUIっぽい感じかなと思います。 言葉だけでは不十分な気がするのですが、 伝わりますでしょうか? --- > フォルダAはtext1?、フォルダBはtext2?、フォルダCはtext3?のような? そうです 個人的にはちょっと違和感があります。 iPhoneのメモでは、おそらく、メモ1つがEntity1つに対応していると思います。 フォルダの概念を取り入れるとしたら、 フォルダのEntityがあって、メモのEntityがあって、 フォルダとメモの関係(リレーションシップ)が「1:多」になるかなと思いました。 (フォルダ1つに対して、メモが多数の関係)
guest

0

ごめんなさい。
やっぱりコードからどうしたいのか理解するのが難しいです・・

とてもややこしいのが、遷移したいのは、FolderRowの中のfolderRowArrayなので、

おそらくこの部分だと思うのですが、
ご自身の中で整理しきれていないからか、
それを他者がコードから理解するのは、とても大変になっている気がします・・

  1. コードのビルドエラーを解消したいのか、
  2. ビルドエラーはない状態で、仕様を実現するための方法を知りたいのか

このどちらかに絞り込んだ内容にしないと、
ちょっと回答するのが難しいかもしれません。
(現在のコードはビルドエラーもあり、仕様を実現するための方法も知りたい、という状況ですよね)

根本的な方針として普通ではないかなと感じたところを1点書いておきたいと思います。
ContentViewのvar folderRow: FolderRowの部分です。
FolderRowはビュー(画面)の構造体ですが、
これをプロパティに持つケースは見たことがないです。
プロパティに持つとしたら、おそらく、
セクションタイトルと固定のリストの情報になると思います。

細かい仕様を把握しきれていないと思うので、
違うところはたくさんあると思いますが、
固定のリスト(セクション)を表示するサンプルのコードを書いてみました。

swift

1import SwiftUI 2 3struct ContentView: View { 4 private let list1 = [ 5 SampleStruct(sectionTitle: "A", listContent: ["elementA1", "elementA2", "elementA3"]), 6 SampleStruct(sectionTitle: "B", listContent: ["elementB1", "elementB2", "elementB3"]), 7 SampleStruct(sectionTitle: "C", listContent: ["elementC1", "elementC2", "elementC3"]), 8 ] 9 10 var body: some View { 11 List { 12 ForEach(list1) { item in 13 Section(item.sectionTitle) { 14 ForEach(item.listContent, id: \.self) { item2 in 15 Text(item2) 16 } 17 } 18 } 19 } 20 } 21} 22 23struct SampleStruct : Identifiable { 24 let id = UUID() 25 let sectionTitle: String 26 let listContent: [String] 27} 28 29struct ContentView_Previews: PreviewProvider { 30 static var previews: some View { 31 ContentView() 32 } 33}

可能でしたら、これを踏まえて、ビルドエラーがない状態まで
質問欄のコードを修正できますでしょうか?

もしそれができない場合は、この質問はビルドエラーを解消するまでで一旦終わらせた方が良いと思いました。


SwiftUIのチュートリアルも実践してみると良いかもしれません。

Introducing SwiftUI
https://developer.apple.com/tutorials/swiftui/


ArrayView()を追加修正しました。

わざわざコメントありがとうございます。
こちらも見ましたよ。

改行対応いたします

こちらもわざわざコメントありがとうございます。
いつでも大丈夫ですよ。

投稿2023/04/02 15:41

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ruru313245

2023/04/03 00:56

ご回答ありがとうございます 自分でも、ここまで複雑になるのだろうか? という思いを持ちながらだったので、 方法がちがうのだと思います。 意としてるのは、iPhoneのメモの追加フォルダです あとから追加してるにもかかわらず、そのそれぞれをタップすると、そのそれぞれの配列に遷移します あの構造をつたえたつもりでしたが、 プレビューコントローラーにもfolderRowへの言及の必要が書かれ、そんなこと通常であり得るの?という心情です。 いずれにしても、いただいたコードを元に修正してみます。
ruru313245

2023/04/03 01:14

プレビューコントローラーはプレビュープロバイダーです
guest

0

ちょっとまだ質問の内容を理解しているところですが、
先にコードの段落について、
ちゃんと伝えられていなかったみたいですので、
先に書き込みしますね。
(コードを書き込みしたかったので、コメントではなく、回答欄に書き込みしますね)

質問欄のコードでは、
改行せずに1行で記述しているところがあると思います。
次のコードです。

swift

1List{Section(header: Text("A")){ForEach(items) { item in NavigationLink(destination: folderRow.folderRowArray, label: {FolderRow(folderLowArray: folderRowArray, folderRowSystemNameText: "gear", folderLowName: "ギア")})}} }

上のコードはちゃんと「{」の後に改行してもらえると、
回答者に優しいと思いました。
次のような感じです。

swift

1List { 2 Section(header: Text("A")) { 3 ForEach(items) { item in 4 NavigationLink(destination: folderRow.folderRowArray, label: { 5 FolderRow(folderLowArray: folderRowArray, folderRowSystemNameText: "gear", folderLowName: "ギア") 6 }) 7 } 8 } 9}

コードを読むのはやっぱり大変ですので、
少しでも読みやすいようにしてあげると良いかなと思いました。
*自分でコードを読む時にも読みやすいようにしておいた方がミスに気づけるようになると思います

投稿2023/04/02 11:28

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ruru313245

2023/04/02 11:43

ありがとうございます 1行で というのは、そういうことですね やはりコードは読むのが大変なんですね わかりました 配慮ある助言ありがとうございます
ruru313245

2023/04/02 11:49

コード修正でニアミスがあったようです ArrayView()を追加修正しました。 すみません ご確認をお願いします
ruru313245

2023/04/02 12:06

本日は、 改行の修正ができないため 明日以降 改行対応いたします
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問