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

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

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

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

Q&A

解決済

1回答

407閲覧

UserDefaultsに保存したstringArrayをObjectとして扱いたいです

ColumbiaUchida

総合スコア12

Swift

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

0グッド

0クリップ

投稿2022/08/14 02:40

こんにちは、この質問を開いていただきありがとうございます!
3日間悩んだ末、答えにたどり着かなかったので質問させていただきます。

UserDefaultsに保存したオブジェクトの配列(JSON形式)をエンコードしたいのですが、うまくいきません。そこでまずは現在のコードを共有させていただきます。

以下のようにしてstringArrayをdecodeする試みをしています(なぜかdata?.data(forKey:)では読み込まれなかったのでstringArrayにしています)。

swift

1 func getSnapshot(in context: Context, completion: @escaping (ExampleEntry) -> ()) { 2 let data = UserDefaults.init(suiteName:widgetGroupId) 3 4 if let tagsData = data?.stringArray(forKey: "favorite1") { 5 do { 6 NSLog("Ohayo: \(tagsData)") 7 let tags = try decoder.decode([TagModel].self, from: tagsData) 8 let result = ExampleEntry(date: Date(), tags: tags) 9 completion(result) 10 } catch { 11 print("Unable to decode tags") 12 } 13 } 14 15 let testEntry = ExampleEntry(date: Date(), tags: [TagModel(id: 1, body: "test")]) 16 completion(testEntry) 17 } 18 19struct TagModel: Codable, Identifiable { 20 let id: Int 21 let body: String 22} 23 24struct ExampleEntry: TimelineEntry { 25 let date: Date 26 let tags: [TagModel] 27}

しかし、このコードではうまく動きません。

NSLog("Ohayo: \(tagsData)")で出力される結果として、

Ohayo: ["{"id":1,"body":"면과"}", "{"id":2,"body":"여행"}", "{"id":3,"body":"책들"}"]

このように出力されるものの、decodeメソッドのtagsDataで渡しているデータ型が違うからだというところまでは理解できたのですが、どうしたら[TagModel]の形で扱えるようになるかがわかりません。

最終的には

swift

1ExampleEntry(date: Date(), tags: [TagModel(id: 1, body: "test")])

というような形で扱いたいと考えているため、お力添えいただけますと幸甚です。

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

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

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

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

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

hoshi-takanori

2022/08/14 02:53

TagModel を JSON 化したものの配列になってるようなので、各文字列をデコードすれば良いのでは。 というか、どうやって保存してるんですか? (その逆をすれば良いはず…。)
ColumbiaUchida

2022/08/14 04:14

コメントありがとうございます! 各文字列をデコード、というのは `"{"id":1,"body":"면과"}"` `"{"id":2,"body":"과"}"` これらを順番にデコードしていくということでしょうか? 実は保存はFlutter側で行っておりまして、よくある形で ```dart class TagModel { int id; String body; TagModel({required this.id, required this.body}); Map toJson() { return { 'id': id, 'body': body, }; } static TagModel fromJson(Map json) { return TagModel( id: json['id'], body: json['body'], ); } } ``` このようにしつつ、SharedPreferenceライブラリを使って保存しております。そのため、Flutterで保存した文字列をSwiftでデコードしたい、ということでした。言葉足らずですみません。
hoshi-takanori

2022/08/14 04:25

let tags = try tagsData.map { try JSONDecoder().decode(TagModel.self, from: $0.data(using: .utf8)!) } とか?
ColumbiaUchida

2022/08/14 05:34

コードのご提示ありがとうございます! 配列の中身をmapで一つずつ回しており、その要素のdataをTagModelでデコードしている、という解釈で合っておりますか? 写経してみたのですが、見たことのないエラーでググってもよくわからなくなってしまいました。 https://photos.app.goo.gl/Dgwx5J3w7ctUvXJp6
hoshi-takanori

2022/08/14 06:36

質問文中のコード if let tagsData = data?.stringArray(forKey: "favorite1") { が前提です。
ColumbiaUchida

2022/08/14 06:57

何度もすみません! いま試してみたところ、無事にオブジェクトにデコードすることが出来ました。 本当にありがとうございます。 ベストアンサーに選ばせていただきたいのですが、こちらからだと回答でないため選べないようでした。 おかげで3日分の悩みが解消されて、とても気分良く日曜日を過ごせそうです。 ありがとうございました!
guest

回答1

0

ベストアンサー

まず、Stringの配列をJSON文字列に変換して、

swift

1let tagsDataJSON = "[" + tagsData.joined(separator: ",") + "]" 2print(tagsDataJSON) 3//=> [{"id":1,"body":"면과"},{"id":2,"body":"여행"},{"id":3,"body":"책들"}]

でもってデコード?

swift

1let tags = try decoder.decode([TagModel].self, from: tagsDataJSON.data(using: .utf8)!) 2print(tags) 3//=> [Main.TagModel(id: 1, body: "면과"), Main.TagModel(id: 2, body: "여행"), Main.TagModel(id: 3, body: "책들")]

投稿2022/08/14 14:24

fuzzball

総合スコア16731

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

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

ColumbiaUchida

2022/08/15 05:05

ご回答いただきありがとうございます! 一度JSON文字列に変換する、という発想がなかったのでとても勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問