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

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

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

Q&A

2回答

1148閲覧

【SwiftUI】リストに検索機能をつけたいのですが、息詰まっています。。。

mottyan09

総合スコア0

0グッド

0クリップ

投稿2022/07/29 01:33

前提

SwiftUIで筋肉のリストのような物を作っています。

筋肉のリストの数が多いので検索機能をつけたいのですが、エラーが出てしまいます

Mmscleの配列の中からこの以下のコードを使って、検索できるようにしたいのですがエラーが発生してしまいます。何かコードの書き方が間違っているのかと思うのですが、教えて頂けると助かります。

コードの全体はこんな感じです。
エラーに関係なさそうなところはカットしています。

import SwiftUI struct Muscle: Identifiable { var id: Int let name: String let image: Image let move: String let origin: String let stop: String } struct ContentView: View { @State var searchText: String = "" let Muscles:[[Muscle]] = [ [.init(id: 0, name: "鎖骨下筋", image: Image("鎖骨下筋"), move:"水平屈強", origin: "ここが始まりだよ", stop: "ここが終わりだよ"), .init(id: 1, name: "小胸筋", image: Image("小胸筋"), move:"マッチョベリマッチョ", origin: "", stop: ""), .init(id: 2, name: "前鋸筋", image: Image("前鋸筋"), move:"水平屈強", origin: "", stop: “”), .init(id: 3, name: "小菱形筋", image: Image("小菱形筋"), move:"水平屈強", origin: "", stop: ""),], [ .init(id: 0, name: "三角筋", image: Image("三角筋"), move:"水平屈強", origin: "", stop: ""), .init(id: 1, name: "大胸筋", image: Image("大胸筋"), move:"水平屈強", origin: "", stop: ""), .init(id: 3, name: "棘下筋", image: Image("棘下筋"), move:"水平屈強", origin: "肩甲下筋", stop: "鳥口腕筋"), .init(id: 4, name: "鳥口腕筋", image: Image("鳥口腕筋"), move:"水平屈強", origin: "肩甲下筋", stop: "肩甲下筋")],] // 配列から情報を取り出すところ、エラーが出てしまう。 var filterMuscles: [String] { if searchText.isEmpty { return Muscles } else { return Muscles.filter { $0.name.contains(searchText) } } } var body: some View { NavigationView { List { ForEach(Muscles.startIndex...(Muscles.endIndex - 1), id: \.self) { section in Section(header: Text(self.swithHeaderTitle(section: section)) .font(.system(size: 30)) .fontWeight(.heavy) ) { ForEach(self.Muscles[section]) { Muscle in MuscleRow(Muscle: Muscle, move: self.swithHeaderTitle(section: section) ) } }.frame(height: 70) } }.navigationTitle(Text("筋肉図鑑")) .searchable(text: $searchText) } } var body: some View { NavigationView { List { ForEach(Muscles.startIndex...(Muscles.endIndex - 1), id: \.self) { section in Section(header: Text(self.swithHeaderTitle(section: section)) .font(.system(size: 30)) .fontWeight(.heavy) ) { ForEach(self.Muscles[section]) { Muscle in MuscleRow(Muscle: Muscle, move: self.swithHeaderTitle(section: section) ) } }.frame(height: 70) } }.navigationTitle(Text("筋肉図鑑")) .searchable(text: $searchText) } }

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

// ここがエラーが出てしまった箇所です。 var filterMuscles: [String] { if searchText.isEmpty { return Muscles } else { return Muscles.filter { $0.name.contains(searchText) } } } // エラーメッセージ Cannot convert return expression of type '[[Muscle]]' to return type '[String]' Cannot convert return expression of type '[[Muscle]]' to return type '[String]' Value of type '[Muscle]' has no member 'name'

質問が分かりずらかったらすみません。
一日かけて色々試してみましたが上手くいかず質問させて頂きました。

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

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

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

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

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

mottyan09

2022/07/29 03:17

var filterMuscles: [[Muscle]] { if searchText.isEmpty { return Muscles } else { return Muscles.filter { $0.name.contains(searchText) } } } 戻り値の型を[[Muscle]]に変えてみましたところ、次のエラーが出てしまいます。 エラーメッセージ→Value of type '[Muscle]' has no member 'name' 配列の書き方が良くないのでしょうか?
hoshi-takanori

2022/07/29 12:12

検索しない状態では 2 つのセクションに分けて表示しているようですが、検索した場合はどのように表示したいのでしょうか?
mottyan09

2022/07/30 02:03

ご返答いただきありがとうございます! コードが見やすいように2セクションで表示していますが、本当は9セクションぐらいあります。 検索した状態では、セクション関係なく.nameで検索かけてその.nemeが中にある配列を取り出したいと思っています。 今質問していただいて思ったのですが、セクションごとに分けてしまうとセクション関係なく検索するっていいうのは難しいのかなと、、、。
guest

回答2

0

検索した状態では、セクション関係なく.nameで検索かけてその.nemeが中にある配列を取り出したいと思っています。

例えばこんな感じでしょうか?

swift

1struct ContentView: View { 2 let allMuscles: [[Muscle]] = // 略 3 4 @State var searchText: String = "" 5 6 // 配列から情報を取り出す (外側の配列の長さが 1 なら、検索結果) 7 var filterMuscles: [[Muscle]] { 8 if searchText.isEmpty { 9 return allMuscles 10 } else { 11 // まず、Muscle をすべて一つの配列にする 12 let joinedMuscles = allMuscles.joined() 13 // 検索 14 let filterMuscles = joinedMuscles.filter { $0.name.contains(searchText) } 15 // 検索結果をさらに配列に入れて返す 16 return [filterMuscles] 17 18 // または、まとめて次の 1 行でも書ける (flatMap の方が良いかも?) 19 // return [allMuscles.joined().filter { $0.name.contains(searchText) }] 20 } 21 } 22 23 var body: some View { 24 NavigationView { 25 List { 26 // 何度も filterMuscles を呼ぶのは無駄なので、変数に入れる 27 let muscles = filterMuscles 28 ForEach(muscles.indices, id: \.self) { section in 29 // swithHeaderTitle が何してるかよく分からないけど、これでいい? 30 let sectionTitle = muscles.count == 1 ? "検索結果" : swithHeaderTitle(section: section) 31 Section(header: Text(sectionTitle) 32 .font(.system(size: 30)) 33 .fontWeight(.heavy) 34 ) { 35 ForEach(muscles[section]) { muscle in 36 MuscleRow(muscle: muscle, move: sectionTitle) 37 } 38 }.frame(height: 70) 39 } 40 }.navigationTitle(Text("筋肉図鑑")) 41 .searchable(text: $searchText) 42 } 43 } 44}

投稿2022/07/30 03:04

編集2022/07/30 03:17
hoshi-takanori

総合スコア7895

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

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

mottyan09

2022/08/05 04:06

丁寧に教えてくださりありがとうござます! Joined()で配列追加できたのは、勉強になりました!! let Muscles:[[Muscle]] = [ [.init(id: 0, name: "鎖骨下筋", image: Image("鎖骨下筋"), move:"水平屈強", origin: "ここが始まりだよ", stop: "ここが終わりだよ"), .init(id: 1, name: "小胸筋", image: Image("小胸筋"), move:"マッチョベリマッチョ", origin: "", stop: ""), .init(id: 2, name: "前鋸筋", image: Image("前鋸筋"), move:"水平屈強", origin: "", stop: “”), .init(id: 3, name: "小菱形筋", image: Image("小菱形筋"), move:"水平屈強", origin: "", stop: ""),], 検索はできたもののここの1つのセクションの中の要素しか検索が掛けられず、やはり配列の書き方変えた方がいいかと思いそっから変えてようやくセクション問わず検索できるようになりました! ご協力いただきありがとうございます!!
guest

0

Muscles[[Muscle]]型なのに戻り値の型が[String]になっているからですね。
とりあえずfilterMuscles関数の戻り値の型[String][[Muscle]]にしてみては。

Musclesは配列のなかにさらに配列があるという構造で、Musciesfilter$0Muscle型の配列Muscle型ではないので.nameを取り出そうとしても取り出せません。
理由がなければそもそも配列の配列という構造自体考え直した方がいいと思いますが(根本的によくわかっておられない感じなので)、$0をさらにfilterにかけてみるとかどうでしょうか?

投稿2022/07/29 01:48

編集2022/07/29 03:50
RiaFeed

総合スコア2701

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

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

mottyan09

2022/07/29 03:23

ご回答頂き大変助かります。 Cannot convert return expression of type '[[Muscle]]' to return type '[String]' Cannot convert return expression of type '[[Muscle]]' to return type '[String]'こちらのエラー解決することが出来ました! 回答していただいた通り、戻り値の型を[[Muscle]]にしてみたのですが、 Value of type '[Muscle]' has no member 'name'というエラーが出てしまいました。 Musclesのの中にnameはあるのですが、配列の書き方が良くないのでしょうか。 もし宜しければ再度アドバイス頂けたら嬉しいです。
mottyan09

2022/07/30 01:50

アドバイスありがとうございます! 配列の中、に配列を入れる(多次元配列?)の方法で作っていたので上手くフィルターが出来なかったんだなと勉強になりました。型のことも理解しきれていないので勉強になります。 身体の部位ごとに筋肉名を分けたくて多次元配列にしていたのですが、どうしても出来なかったら一旦諦めて一次元配列でやってみようと思います。 $0をさらにfilterというのはどんな書き方なのでしょうか。 RiaFeedもお忙しいと思ういますので、可能でしたら教えて頂きたいです。
RiaFeed

2022/07/30 02:10

部位ごとに分けたいならMuscle型に部位を表す変数を追加してそこに部位の情報を入れたほうが扱いやすいと思いますよ。 $0をさらにfilterはMuscles.filter{$0.filer{}}的な意味ですがあまりお勧めはできないです。
mottyan09

2022/08/05 04:07

やはり配列の書き方から一度見直してみました。 無事に検索かけれるようになりました。 ご協力いただきありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問