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

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

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

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

解決済

SwiftUIにてAPIを利用してデータを取得してからViewを更新する方法がわからない

Beruto
Beruto

総合スコア10

Swift

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

1回答

0評価

0クリップ

258閲覧

投稿2022/01/12 14:10

編集2022/04/28 09:39

SwiftUIにてアプリ開発を行っているのですが、APIを使ってデータを取得してからViewを更新する方法がわかりません。
initに、データ取得の関数、view更新の関数を順に呼び出しているのですが、
データが取得し終わる前にview更新の関数が呼び出されてしまい、画面になにも表示されません。

以下、イメージのコードです

swift

struct SwiftApiTest: View { @ObservedObject var viewModel = SwiftApiTestViewModel(count: 10) var body: some View { if viewModel.isProgress { ProgressView() } else { VStack { ForEach(viewModel.subViews) {view in view } } } } } struct SubView: View, Identifiable { let id = UUID() let hoge: Int let fuga: String init?(hoge: Int?, fuga: String?) { if let hoge = hoge, let fuga = fuga { self.hoge = hoge self.fuga = fuga } else { print("hogeかfugaがnilです") return nil } } var body: some View { HStack { Text("hoge: \(hoge)") Text("fuga: \(fuga)") } } } class SwiftApiTestViewModel: ObservableObject { @Published var cm = CommunicationManager() @Published var subViews: [SubView] = [] init(count: Int) { // データ取得 resume() // view更新処理 // 上のresume()がまだ終わっていないのに呼び出されてしまう subViewDuplicator(count: count) } var isProgress: Bool { cm.isProgress } var hoge: Int? { var value: Int? if let data = cm.apiData { value = data.hoge } return value } var fuga: String? { var str: String? if let data = cm.apiData { str = data.fuga } return str } // SubViewをcount分だけ複製して配列に入れる func subViewDuplicator(count: Int) { for _ in 0..<count { subViews.append(SubView(hoge: hoge, fuga: fuga)!) } } func resume() { cm.resume() } } class CommunicationManager { struct ApiData: Decodable { var hoge: Int var fuga: String } // 処理中か var isProgress = false // 取得するデータ var apiData: ApiData? func resume() { // 処理開始 isProgress = true let url = URL(string: "url")! let request = URLRequest(url: url) URLSession.shared.dataTask( with: request, completionHandler: { data, response, error in // データ取得処理 }) // 処理終了 isProgress = false } }

ものすごい雑なサンプルですが、現在作成中のアプリでは
天気apiを使って取ってきた情報(1週間天気など)を一旦別View(ここではSubView)にいれ
それを配列にしてメインViewにてForEachを使って表示させています。

resume()が終わってからsubViewDuplicator()を実行させる方法を教えていただきたいです。
DispatchQueue.main.asyncなどを使うようではありますが色々試してうまく行かなかったので
質問させていただきます。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

hoshi-takanori

2022/01/15 16:01

ツッコミどころが多すぎてどこからコメントしたらいいか悩みますが、とりあえず非同期処理について学ぶことをお勧めします。

まだ回答がついていません

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

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Swift

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