非同期で呼び出す仕組み
import SwiftUI struct ContentView: View { @State private var temperature: String = "__" @State private var windspeed: String = "__" @State private var showSheet = false var body: some View { VStack(spacing: 20) { Text("東京の現在天気") .font(.title) Text("気温: \(temperature)°C") Text("風速: \(windspeed)m/s") Button("天気を取得") { Task { await fetchWeather() } } Button("詳細を表示(ボトムシート)") { showSheet = true } } .padding() .sheet(isPresented: $showSheet) { BottomSheetView( temperature: temperature, windspeed: windspeed ) .presentationDetents([.fraction(0.3), .medium, .large]) .presentationDragIndicator(.visible) } } func fetchWeather() async { guard let url = URL(string: "https://api.open-meteo.com/v1/forecast?latitude=35.6895&longitude=139.6917¤t_weather=true") else { return } do { // 非同期で通信(完了を待つ) let (data, _) = try await URLSession.shared.data(from: url) let decoded = try JSONDecoder().decode(WeatherResponse.self, from: data) // メインスレッドでUI更新 await MainActor.run { self.temperature = String(decoded.current_weather.temperature) self.windspeed = String(decoded.current_weather.windspeed) } } catch { print("エラー: \(error.localizedDescription)") } } } struct BottomSheetView: View { let temperature: String let windspeed: String var body: some View { VStack(spacing: 16) { Text("詳細情報") .font(.title3) .bold() Text("気温: \(temperature)°C") Text("風速: \(windspeed)m/s") Text("データ提供: open-meteo.com") .font(.footnote) .foregroundColor(.gray) } .padding() } } struct WeatherResponse: Codable { struct CurrentWeather: Codable { let temperature: Double let windspeed: Double } let current_weather: CurrentWeather } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
fetchWeather() に async を付ける 非同期処理を行う関数になる
Task { await fetchWeather() } SwiftUI のボタン内で非同期関数を呼ぶための安全な方法
try await URLSession.shared.data(from:) 通信が完了するまで待機(コールバック不要)
await MainActor.run { … } UI更新は常にメインスレッドで行う
うん、asyncは他の言語でもよく出てくるのでわかりやすい。