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

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

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

Q&A

解決済

1回答

2117閲覧

swiftuiのTextFieldで入力・編集したリスト内テキストの保存がuserDefaultsでうまくできない

naki888

総合スコア12

0グッド

2クリップ

投稿2020/10/15 10:09

swiftuiでリストを作成しており、入力した文言を編集可能にし、都度保存するようなアプリを作成しています。

swiftuiでの保存はuserDefaultsを使用するとのことだったので、TextFieldでのコード実行後に、userDefaultsを組み込んだのですがエラーが出てしまいます。

エラーはNavigationviewの箇所とリストのForEach内部となっています。

Type 'Void' cannot conform to 'View'; only struct/enum/class types can conform to protocols

Value of optional type '[Any]?' must be unwrapped to refer to member 'count' of wrapped base type '[Any]'

どの部分が間違っているのかわからず困っています。ご指導いただければ幸いです。

swift

1import SwiftUI 2 3struct ContentView: View { 4 5 @State var tasks = ["リスト1", "リスト2", "リスト3", "リスト4", "リスト5"] 6 //@State var tasks = [String]() 7 @State var newtask = "" 8 var userDefaults = UserDefaults.standard 9 10 11 var body: some View { 12 VStack { 13 NavigationView{ 14 List{ 15 ForEach(0..<tasks.count, id: .self) { index in 16 TextField("PlainTextFieldStyle", text: $tasks[index])} 17 //Text(self.tasks[task])} 18 .onDelete(perform: rowRemove) 19 } 20 .navigationBarTitle("Menu") 21 let tasks = userDefaults.array(forKey: "キー") 22 userDefaults.set(tasks, forKey: "キー") 23 } 24 HStack { 25 Spacer() 26 Button(action: { 27 self.tasks.append(self.newtask) 28 self.newtask = "" 29 //self.tasks = createTasks() 30 }) { 31 Image(systemName:"pencil.tip.crop.circle.badge.plus") 32 .resizable() 33 .foregroundColor(/*@START_MENU_TOKEN@*/.black/*@END_MENU_TOKEN@*/) 34 .padding(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/) 35 .scaledToFit() 36 .frame(width: 80, height: 80) 37 } 38 } 39 } 40 } 41 42 func rowRemove(offsets: IndexSet) { 43 tasks.remove(atOffsets: offsets) 44 } 45} 46 47struct ContentView_Previews: PreviewProvider { 48 static var previews: some View { 49 ContentView() 50 } 51}

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

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

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

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

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

guest

回答1

0

ベストアンサー

この度は私も大変勉強になりました。ありがとうございました。
NavigationView内でUserDefaultsを使用したためエラーとなっているようです。
TextFieldからonCommitにてイベントを受け取って保存するとエラーが無くなりました。

Swift

1 NavigationView{ 2 List{ 3 ForEach(0..<tasks.count, id: .self) { index in 4 TextField("PlainTextFieldStyle", text: self.$tasks[index] , onCommit: { 5 6 UserDefaults.standard.set(self.tasks, forKey: "キー") 7 8 }) 9 } 10 .onDelete(perform: rowRemove) 11 12 } 13 14 }

投稿2020/10/16 03:35

lucia0320

総合スコア15

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

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

naki888

2020/10/16 05:15

ご教示ありがとうございます。UserDefaultsの使用方法の方大変勉強になります。 ForEachに表示される下記の部分の対応でtasks.countのtasksの後に?や!をつけてもエラーになってしまいます。このエラーはリスト内の全てが削除されることを懸念してエラーが出ているのかと思うのですが、?でnilの場合も含める形では対応できないのでしょうか。 Value of optional type '[Any]?' must be unwrapped to refer to member 'count' of wrapped base type '[Any]' こちらの問題点もご存知でしたらご指摘いただければ大変ありがたいです。何卒よろしくお願いいたします。
lucia0320

2020/10/16 06:05 編集

ご確認ありがとうございます。 tasks.countでnilの場合ですが、 宣言部にて空配列を宣言しても正常に動作しました。 ?若しくは!を付与するとエラーとなる原因は私には分からず申し訳御座いませんが tasksを空配列として宣言してもエラーとならないので Listが全て削除されることを懸念してエラーとなっている。ということとは少し違うようです。 <変更前> @State var tasks = ["リスト1", "リスト2", "リスト3", "リスト4", "リスト5"] <変更後> @State var tasks = [String]() //空配列 なお、Playgroundにて下記のプログラムを実行したところ 正しく、「0」が返ってきました。 import SwiftUI var tasks = [String]() print(tasks.count)   //0
naki888

2020/10/16 07:01

ご丁寧にありがとうございます。この度は大変助かりました。 もしかしたらxcode12の仕様変更などが絡んでいるのかもしれませんので、確認してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問