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

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

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

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

Swift

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

Q&A

解決済

1回答

698閲覧

For文の中の非同期処理でリストを作成し、For文外で使用したい

abc1222

総合スコア24

非同期処理

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

Swift

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

0グッド

0クリップ

投稿2020/12/17 07:30

編集2020/12/17 10:16

前提・実現したいこと

For文の中の非同期処理でリストを作成し、For文の外でリストを活用したいと考えています。
しかし、非同期処理なので、For文の中の処理を待たずに、リストが空の状態で処理が進みます。
調べていて、DispatchSemaphoreを活用することは分かったのですが、どうも上手くいきません。
使い方が間違っていると思うのですが、調べても原因が分からず困っています。

発生している問題・エラーメッセージ

処理が進まなくなった。

該当のソースコード

Swift

1let semaphore = DispatchSemaphore(value: 0) 2var testList = [String: Test]() 3 4for value in list { 5 //非同期処理スタート 6 db.collection("Test").document(value) 7 .getDocument { (document, error) in 8 9 if let error = error { 10 print("Error getting documents: (error)") 11 } else { 12 let result = Result { 13 try document?.data(as: Test.self) 14 } 15 switch result { 16 case .success(let resultValue): 17 if let test = resultValue { 18 testList[document!.documentID] = test 19 } else { 20 print("Document does not exist") 21 } 22 case .failure(let error): 23 print("Error decoding city: (cError)") 24 } 25 } 26 semaphore.signal() 27 } // ここまで非同期処理 28 semaphore.wait() 29}//For文終わり 30 31print(testList) //DispatchSemaphoreを使わないと[:]に、使うとたどり着かない

試したこと

semaphore.signal()やsemaphore.wait()の位置を色々変えてみた。

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

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

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

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

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

MasakiHori

2020/12/17 08:10

そもそもFirestoreの使い方間違ってます。
abc1222

2020/12/17 08:21

使い方というのはコードではなく、上記の読み取りが必要な構造が間違っているということでしょうか
MasakiHori

2020/12/17 08:41

addSnapshotListener はdocumentなどに変更があった時に通知を受けるための関数を登録しておくものです。 登録した関数は登録時に一度呼び出された後、変更があるたびに呼ばれます。 変更があるたびに呼ばれるのでこの関数でスレッドのブロックなどを行うと問題が生じます。 この場合はおそらくgetDocument を使うべきだと思われます。(全体見ないとわからないけど)
abc1222

2020/12/17 08:55

なるほど!分かりやすくありがとうございます。 たしかにgetDocumentで良い場所でした! まずは上記を修正します
guest

回答1

0

ベストアンサー

DispatchGroupを使います

swift

1let group = DispatchGroup() 2var testList = [String: Test]() 3 4for value in list { 5 6 // groupのタスク数を増やす 7 group.enter() 8 9 //非同期処理スタート 10 db.collection("Test").document(value) 11 .getDocument { (document, error) in 12 13 defer { 14 // groupのタスク数を減らす 15 group.leave() 16 } 17 18 ... 19 20 } 21} 22 23// groupのタスク数が0になるまで待つ 24group.wait() 25 26print(testList)

投稿2020/12/18 00:50

MasakiHori

総合スコア3391

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

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

abc1222

2020/12/19 01:36

ありがとうございます! 使う物自体が違ったんですね! 思い通りの動きになりました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問