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

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

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

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Swift

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

Q&A

解決済

1回答

1101閲覧

Swift Dictionary(辞書)へのJSONデータ追加

ishiishiyay

総合スコア33

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Swift

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

0グッド

0クリップ

投稿2021/11/25 00:13

編集2021/11/25 02:23

SwiftでDictionaryにJSONデータを追加(append)する方法について、ご質問させてください。
お力添えいただけますと幸いです。よろしくお願いいたします。

サーバーからJSONデータ(自分に来た友達申請情報)を取得し、辞書に格納したあと、
xx秒おきにサーバーを監視し(サーバー監視のロジックは省略させてください)、
もし新たに友達申請が増えていた場合に、その更新分を取得し、辞書に追加したいと考えています。

JSONのデータはこちらです:

//JSONデータ { "number_of_friends_requests": 2, "friends_requests": [ { "users_id": 1, "users_name": "string", "users_thumbnail_image_url": "string" }, { "users_id": 2, "users_name": "string", "users_thumbnail_image_url": "string" } ] }

ViewModel内で、サーバー通信および辞書への格納をしています。

SwiftUI

1 2@Published var friendRequestUsers: FriendsRequestsList? 3 4class SearchFriendViewModel: ObservableObject { 5//中略 6func receiveFriendRequest (skip: Int?, limit: Int?) { 7 8URLSession.shared.dataTask(with: request) { (data, response, error) in 9 10do { 11self.friendRequestUsers = try JSONDecoder().decode(FriendsRequestsList.self, from: data) 12 print("friend requests are (self.friendRequestUsers)") 13//print結果(これは上手く行きます):friend requests are Optional(FriendQA_SwiftUI.FriendsRequestsList(id: 0, numberOfFriendsRequests: 2, friendsRequests: [FriendQA_SwiftUI.FriendsRequests(id: 69, usersName: "Sfaweaw", usersThumbnailImageUrl: "xxx"),FriendQA_SwiftUI.FriendsRequests(id: 68, usersName: "Waiwai", usersThumbnailImageUrl: "xxx")])) 14 15//中略 16 17//ここで更新分の追加を試みましたが、エラーになりビルドができませんでした。 18let newFriendRequest = try JSONDecoder().decode(FriendsRequestsList.self, from: data) 19self.friendRequestUsers.append(newFriendRequest) 20//Value of type 'FriendsRequestsList?' has no member 'append' 21self.friendRequestUsers.addObject(newFriendRequest) 22//Value of type 'FriendsRequestsList?' has no member 'addObject' 23self.friendRequestUsers["xxx"] = newFriendRequest //xxxのkeyに何を書けばいいかわからず 24 25} catch { 26} 27} 28 29} 30

Modelはこちら:

SwiftUI

1 2 struct FriendsRequestsList: Identifiable, Decodable { 3 4 let id: Int 5 let numberOfFriendsRequests: Int 6 let friendsRequests: [FriendsRequests] 7 8 9 enum CodingKeys: String, CodingKey { 10 case id = "users_id" 11 case numberOfFriendsRequests = "number_of_friends_requests" 12 case friendsRequests = "friends_requests" 13 } 14 15 init(from decoder: Decoder) throws { 16 17 let container = try decoder.container(keyedBy: CodingKeys.self) 18 19 self.id = try container.decodeIfPresent(Int.self, forKey: .id) ?? 0 20 self.numberOfFriendsRequests = try container.decodeIfPresent(Int.self, forKey: .numberOfFriendsRequests) ?? 0 21 self.friendsRequests = try container.decodeIfPresent([FriendsRequests].self, forKey: .friendsRequests) ?? [FriendsRequests]() 22 23 } 24 25 } 26 27 struct FriendsRequests: Identifiable, Decodable { 28 let id: Int 29 let usersName: String 30 let usersThumbnailImageUrl: String 31 32 33 enum CodingKeys: String, CodingKey { 34 case id = "users_id" 35 case usersName = "users_name" 36 case usersThumbnailImageUrl = "users_thumbnail_image_url" 37 } 38 39 init(from decoder: Decoder) throws { 40 41 let container = try decoder.container(keyedBy: CodingKeys.self) 42 43 self.id = try container.decodeIfPresent(Int.self, forKey: .id) ?? 0 44 self.usersName = try container.decodeIfPresent(String.self, forKey: .usersName) ?? "" 45 self.usersThumbnailImageUrl = try container.decodeIfPresent(String.self, forKey: .usersThumbnailImageUrl) ?? "" 46 47 } 48 49 50 }

お力添えいただけますと幸いです。よろしくお願いいたします。

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

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

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

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

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

hoshi-takanori

2021/11/25 00:39

> xx秒おきにサーバーを監視 プッシュ通知を使った方が良いのでは。
ishiishiyay

2021/11/25 00:43

hoshi-takanoriさん、コメントいただきありがとうございます!プッシュ通知も実装しますが、通知を許可しないユーザーもいるため、画面で友達申請一覧を表示し、リアルタイムに更新したいと思っています!
hoshi-takanori

2021/11/25 00:51

なるほど。ポーリングは感心しませんが、特定の画面だけとかなら許せる範囲かな…。 ところで、FriendsRequestsList はどんな型でしょうか?
ishiishiyay

2021/11/25 02:25

hoshi-takanoriさん、早速にありがとうございます! >>ポーリングは感心しませんが もしよろしければ、こちらの理由についてお伺いしてもよろしいでしょうか? >>ところで、FriendsRequestsList はどんな型でしょうか? ごめんなさい、記載不足でした。本文に追記させていただきました! お手数ですが、よろしくお願いいたします...!
hoshi-takanori

2021/11/25 03:16

ポーリング (定期的に情報を取りに行くこと) が良くないのは、xx 秒おきに通信を行うことで、スマホの電池や通信の無駄遣いになるからです。特に、アプリ起動中はどの画面でもとか、アプリがバックグラウンドに回ったり画面がロックされてもポーリングを続けるのはやめるべきですね。 FriendsRequestsList の定義ありがとうございます。 friendRequestUsers は SearchFriendViewModel クラスのプロパティってことですよね? > self.friendRequestUsers.append(newFriendRequest) > //Value of type 'FriendsRequestsList?' has no member 'append' append は配列のメソッドですが、friendRequestUsers は配列ではなく構造体なのでそんなメソッドはないってことですね。newFriendRequest の中の friendsRequests を、friendRequestUsers の中の friendsRequests に append(contentsOf:) すれば良いような気がしますが、その前に重複チェックすべきでは? とか、numberOfFriendsRequests も更新する必要があるかも? とか、変更するプロパティは let じゃなくて var にする必要が、とか、friendRequestUsers が Optional なのを何とかする必要が、とか、いろいろ考える必要がありそうですね…。
ishiishiyay

2021/11/25 06:18 編集

ポーリングについて、ご詳細にありがとうございます!なるほどです。例えばLINEメッセージの一覧画面(10人くらいとのやりとりが表示されている画面)を開いている時に、誰かから新しいLINEが来たら、それが一番上に自動的に表示されて更新されると思うのですが、あれをやろうと思ったら、ポーリング以外の実装方法はあるのでしょうか? (WebSocketというのを使うかどうかも検討したのですが、コストがかかるようで、やめました) 教えてもらった通りにやったら無事に追加できました!!本当にありがとうございます。 (letをvarに変え、 self.friendRequestUsers?.numberOfFriendsRequests = newFriendRequest.numberOfFriendsRequestsの1行も足したら、リクエスト数も更新することができました。)
hoshi-takanori

2021/11/25 06:33

LINE がどう実装してるかは知りませんが、タイムラインのような更新頻度が高く、かつリアルタイム性の求められるものは WebSocket の可能性は高いと思いますが、友達申請はそこまででもないのでは。(ブッシュ通知と、画面が切り替わった時や手動での更新で充分では?)
ishiishiyay

2021/11/25 09:42

hoshi-takanoriさん、なるほどです、よく分かりました。お時間いただきありがとうございました!!
guest

回答1

0

自己解決

コメント欄の方で解決したため、こちらの質問は閉じさせていただきます。ありがとうございました。

投稿2021/12/01 11:55

ishiishiyay

総合スコア33

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問