質問: self.meta!["{Exif}"] as? NSDictionary //セマフォの値をインクリメント queue.async { semaphore.signal() } }) //本当はこのように上のcompletionHandlerが終わるのを待ってreturn exif したい semaphore.wait() //completionHandlerの中でexifに代入されるのを待たないとここでいつもnilが返されてしまう。 //なのでexifに中身が入るように、completionHandlerが終わるのを待ちたい。 return exif } ``` ### 試したこと 参考にしたのは、 ・ディスパッチセマフォの使い方 ・非同期の、Voidが戻り値のブロックから値を返せるか? (→回答は、非同期のやり方に従え、無理に逆らわない方がいい...的な感じ?) ・Wait for async task to finish completion block before returning in app delegate (ここで、ディスパッチセマフォで待つといいよ的な回答を見て、そうやって待てばいいんか!ってこのやり方を試しています) ### 補足情報(言語/FW/ツール等のバージョンなど) Swift3.0.2、Xcode8(version8.2.1)、iOS10.2で試しました。 使ってるOSはMacOS10.12.3です。 非同期のやり方に従え...変なやり方すんな...的な感じなら教えてください...。 自分の知識不足のせいで変なことやろうとしてる気もするので...。
回答: asset.requestContentEditingInput の処理はgetExifの実行がreturnし、その関数を呼び出した処理が全て終わってから始まるので、セマフォでブロックしてしまってはデッドロック状態になると思います。 requestContentEditingInputの結果をgetExifの呼び出し側に情報として返したいのであれば、 ``` private func getExif(asset : PHAsset)->NSDictionary? ``` の定義を ``` private func getExif(asset :PHAsset, exifCompletionHandler: @escaping (dictionary: NSDictionary?) -> Void) -> Void ``` に変更し、 ``` exif = self.meta!["{Exif}"] as? NSDictionary exifCompletionHandler(exif) ``` としたらどうでしょうか。 getExif()はすぐさまreturnするので、それ以降の処理をgetExif()の引数exifCompletionHandlerにクロージャとして渡すことになります。 ソースコードが書かれた順番で処理されるように、プログラムの見通しをよくしたい場合は、 RxSwiftやPromiseKitなどのフレームワークを使えばある程度可能ですが、 学習コストが要求されるので、まずはcompletionHandlerなどの基本的なやり方をマスターしてはどうでしょうか。