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

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

新規登録して質問してみよう
ただいま回答率
85.38%
非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Swift

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

Q&A

1回答

1371閲覧

swiftuiの非同期処理について、逐次処理をしたい

zakkiblog

総合スコア3

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Swift

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

0グッド

0クリップ

投稿2022/12/22 03:45

編集2022/12/22 04:02

swiftuiの非同期処理についての質問です。

URLSessionで通信を行い取ってきたjsonデータをデコードする一連の処理が非同期で行われ、次の処理にこの結果を使用したいため、この非同期の結果を待って同期的に処理をしたいのですが良い方法が分かりません。

現在は非同期処理の後、3秒間スリープさせてから次の処理に移っています。これが良い方法でないことは分かるのですがこのような場合にどうすればいいのか教えていただけると幸いです。async awaitなども試してみたのです全く上手く行きませんでした。

以下のコードのfor文全体の非同期処理が完了するまで、それ以下の処理を開始するのを待ちたいです。現在はThread.sleep(forTimeInterval: 3)を挿入しています。

swiftui

1func ListCreate() -> (){ 2 DataList = [] 3 print("関数呼ばれる") 4 5 6 for i in 0..<urls.count{ 7 print("urlデータ取得開始,\(i)回目") 8 let url:URL = URL(string: urls[i])! 9 URLSession.shared.dataTask(with: url) { data, response, error in 10 if let jsonData = data { 11 print("urlデータ取得成功\(i)回目") 12 print(jsonData) 13 getJSON(jsonData,i) 14 } else{ 15 print("urlデータ取得失敗\(i)回目") 16 } 17 }.resume() 18 } 19 20 Thread.sleep(forTimeInterval: 3) 21 22 print("全データ取得終了") 23 //構造体のインスタンスにした全データを日付順に並び替え 24 DataList.sort(by:{$0.SortDate > $1.SortDate}) 25 for s in DataList{ 26 print("タイトル: \(s.Title),日付:\(s.Date),サイト名:\(s.SiteName),リンク:\(s.Link)") 27 } 28}

swiftui

1struct Matome: View { 2 var list: () = ListCreate() 3 4 var body: some View { 5 NavigationStack{ 6 List{ 7 ForEach(0..<DataList.count, id: \.self){ index in 8 NavigationLink(destination:OpenWeb(url:DataList[index].Link)){ 9 HStack{ 10 URLImageView(viewModel: .init(url:DataList[index].Image)) 11 .frame(width:60, height:45) 12 VStack{ 13 Text(DataList[index].Title).font(.subheadline).truncationMode(.tail) 14 HStack{ 15 Text(DataList[index].SiteName).font(.caption) 16 Text(DataList[index].Date).font(.caption) 17 } 18 19 } 20 } 21 }//navigationlink 22 }.frame(height:60)//foreach 23 24 }.navigationBarTitle("まとめ",displayMode: .inline).refreshable { 25 ListCreate() 26 } 27 } //navigationstack 28 29 } 30} 31 32

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

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

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

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

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

hoshi-takanori

2022/12/22 05:31

非同期処理を待つのが間違いです。非同期処理を開始したら読み込み中の状態にして、終了したら表示を更新しましょう。
guest

回答1

0

良い方法ではありませんが古典的な方法として、
URLSessionTask.state が全て . completed かどうか
調べる手もあります。

やはり async や await を使えるのがベストかと思われますが
応急処置としては有効な手かと思われます。

申し訳ございませんが
動作チェックはできておりません。

swiftui

1func ListCreate() -> (){ 2 DataList = [] 3 print("関数呼ばれる") 4 var tasks: [URLSessionTask] = [] 5 for i in 0 ..< urls.count { 6 let url:URL = URL(string: urls[i])! 7 var session = URLSession.shared.dataTask(with: url) { data, response, error in 8 if let jsonData = data { 9 print("urlデータ取得成功\(i)回目") 10 print(jsonData) 11 getJSON(jsonData,i) 12 } else{ 13 print("urlデータ取得失敗\(i)回目") 14 } 15 } 16 session.resume() 17 tasks.append(session) 18 } 19 20 var endFlg = false 21 while(!endFlg){ 22 endFlg = true 23 for i in 0 ..< tasks.count { 24 if tasks[i].state != .completed { 25 endFlg = false 26 Thread.sleep(forTimeInterval: 0.1) 27 break 28 } 29 } 30 } 31 32 print("全データ取得終了") 33 //構造体のインスタンスにした全データを日付順に並び替え 34 DataList.sort(by:{$0.SortDate > $1.SortDate}) 35 for s in DataList{ 36 print("タイトル: \(s.Title),日付:\(s.Date),サイト名:\(s.SiteName),リンク:\(s.Link)") 37 } 38 }

投稿2022/12/28 05:45

編集2022/12/28 05:54
uni2

総合スコア258

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

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

zakkiblog

2022/12/28 14:42

ありがとうございます。思い通りの挙動が出来ました。自分でもasync awaitが使えるように模索してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

アカウントをお持ちの方は

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

ただいまの回答率
85.38%

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

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

質問する

関連した質問