ioli
@ioli (いおり)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

bool型の配列をUserDefaultsを用いて保存または更新する方法

SwiftUIにおいてUserDefaultsで配列を保存する方法

現在SwiftUIで複数のボタンのon.offをboolの配列で管理して、それをもとにボタンの浮き沈みを表現するようの手法をとっています。
このboolの配列を保存するために、UserDefaultsを用いて保存しようとしたのですがうまくいきませんでした。

元の簡易的なコード

struct test: View {
    @State var flags = [false,false]

    var body: some View {
        VStack{
            Button(action: {
                flags[0].toggle()
            }) {
                Text("button1")
                    .font(.title2)
                    .foregroundColor(Color.white)
                    .padding(.all)
                    .background(Color.blue)
                    .shadow(color: .gray, radius:flags[0] ? 0:4, x: flags[0] ? 0 : 5, y: flags[0] ? 0 : 5)
                    .offset(x: flags[0] ? 5 : 0,y: flags[0] ? 5 : 0)
            }

            Button(action: {
                flags[1].toggle()
            }) {
                Text("button2")
                    .font(.title2)
                    .foregroundColor(Color.white)
                    .padding(.all)
                    .background(Color.blue)
                    .shadow(color: .gray, radius:flags[1] ? 0:4, x: flags[1] ? 0 : 5, y: flags[1] ? 0 : 5)
                    .offset(x: flags[1] ? 5 : 0,y: flags[1] ? 5 : 0)
            }
        }
    }
}

スクリーンショット 2021-05-30 17.09.47.png

自分なりに表現したコード

class Flags: ObservableObject {
    @Published var flags : [Array<Bool>]

    func flagupdate(num:Int){
        var flag:[Bool] = UserDefaults.standard.array(forKey: "flags") as! [Bool]
        flag[num].toggle()
        UserDefaults.standard.set(flag, forKey: "flags")
    }

    init() {
        flags = UserDefaults.standard.array(forKey: "flags") as? Array<Bool> ?? [false,false]
    }
}


struct test: View {
    @State var flags = Flags().flags

    var body: some View {
        VStack{
            Button(action: {
                Flags().flagupdate(num: 0)
            }) {
                Text("button1")
                    .font(.title2)
                    .foregroundColor(Color.white)
                    .padding(.all)
                    .background(Color.blue)
                    .shadow(color: .gray, radius:flags[0] ? 0:4, x: flags[0] ? 0 : 5, y: flags[0] ? 0 : 5)
                    .offset(x: flags[0] ? 5 : 0,y: flags[0] ? 5 : 0)
            }

            Button(action: {
                Flags().flagupdate(num: 1)
            }) {
                Text("button2")
                    .font(.title2)
                    .foregroundColor(Color.white)
                    .padding(.all)
                    .background(Color.blue)
                    .shadow(color: .gray, radius:flags[1] ? 0:4, x: flags[1] ? 0 : 5, y: flags[1] ? 0 : 5)
                    .offset(x: flags[1] ? 5 : 0,y: flags[1] ? 5 : 0)
            }
        }
    }
}

エラーコードが発生する場所

init() {
    flags = UserDefaults.standard.string(forKey: "flags") as? Array<Bool> ?? [false,false]
    }
//エラー内容
//Cannot assign value of type 'Array<Bool>' to type '[Array<Bool>]'
Text("button1")
    .font(.title2)
    .foregroundColor(Color.white)
    .padding(.all)
    .background(Color.blue)
    .shadow(color: .gray, radius:flags[0] ? 0:4, x: flags[0] ? 0 : 5, y: flags[0] ? 0 : 5)
    .offset(x: flags[0] ? 5 : 0,y: flags[0] ? 5 : 0)
//ここの.shadow部分と.offset部分でエラー表示
//Cannot convert value of type 'Array<Bool>' to expected condition type 'Bool'

私自身まだプログラミングについて勉強し始めたばかりであるため、UserDefaultsの使い方を完璧に理解しているわけではありません。とても初歩的な質問をしてしまっていると思いますが、何かご教授頂ければ幸いです。

0

1Answer

@Published var flags : [Array<Bool>][Array<Bool>][Bool]にしてください。

0Like

Comments

  1. @ioli

    Questioner

    ありがとうございます!エラーは出なくなりました!
    しかし、プレビューでボタン1またはボタン2を押した時にクラッシュしています。class内のfuncの書き方が間違っているのでしょうか?
    私としては、配列を取り出して与えられたnumのインデックスのBoolを切り替えて再びUserDefaultsに保存したいのですが…
  2. flagupdate 関数の中で flags 変数を使わずに UserDefaults から値を取り出そうとしているからです。初期状態では UserDefaults に値が入っていないので、 as! が nil をアンラップしようとしてエラーになります。
  3. @ioli

    Questioner

    nilに対して処理をするとクラッシュすることを忘れていました。
    無事自分のやりたい処理ができるようになりました。
    本当にありがとうございます!!!

Your answer might help someone💌