🐷
Swift Playgroundsで非同期処理の完了を待つ方法
ちょとしたSwiftのコードを書きたいときにmacOS版のSwift Playgroundsを使っています。
それなりに使いやすいのですが、非同期処理を書くと実行が完了する前にプログラムが終了してしまうので困っていました。
例えば、以下のようなURLSession
を使ってGitHubのリポジトリ数を取得するコードを実行すると、最後の
code completed.
とだけ表示されてプログラムが終了してしまいます。
import Combine
import Foundation
struct SearchResponse: Decodable {
var totalCount: Int
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let url = URL(string: "https://api.github.com/search/repositories?q=swift")!
var cancellable = URLSession.shared.dataTaskPublisher(for: url)
.tryMap() { element -> Data in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return element.data
}
.decode(type: SearchResponse.self, decoder: decoder)
.sink(receiveCompletion: { print ("Received completion: \($0).") },
receiveValue: { repositories in print ("Received: \(repositories.totalCount).")})
print("code completed.")
調べたところ、PlaygroundPage
のneedsIndefiniteExecution
をtrue
にすると、プログラムが終了せず無期限で実行されるようになるので、結果的に非同期処理が行われるようになります。
具体的にはPlaygrounds
に以下のコードを追加します。
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
先程のコードを例にすると、先頭に上記のコードを追加して実行します。
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
import Combine
import Foundation
struct SearchResponse: Decodable {
var totalCount: Int
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let url = URL(string: "https://api.github.com/search/repositories?q=swift")!
var cancellable = URLSession.shared.dataTaskPublisher(for: url)
.tryMap() { element -> Data in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return element.data
}
.decode(type: SearchResponse.self, decoder: decoder)
.sink(receiveCompletion: { print ("Received completion: \($0).") },
receiveValue: { repositories in print ("Received: \(repositories.totalCount).")})
print("code completed.")
今度は以下のように出力されて非同期処理の実行結果が出力されました。
code completed.
Received: 209193.
Received completion: finished.
このままでは「停止」ボタンを押すかエディタで編集をするまでプログラムが終了しないので、明示的に終了させるために処理の完了後にfinishExecution
を実行します。
なお、PlaygroundPage
が利用できる環境は以下の通りです。
macOS 11.0+
Xcode 10.2+
Swift Playgrounds 2.0+
Discussion