I'm currently testing my Swift
skills while having fun with WeatherKit
but there's something I can't do by myself.
I'd like to "unwrap" the temperature.value
I get from hour
like I did for currenWeather
? Is it possible, if yes, what should I do?
import Foundation
import WeatherKit
class WeatherManager: ObservableObject {
@Published private var currentWeather: CurrentWeather?
@Published private var hourWeather: Forecast<HourWeather>?
var isLoading: Bool
init() {
isLoading = true
Task {
await getWeather(48.864716, 2.349014) /* Paris, France */
}
}
@MainActor
func getWeather(_ lat: Double, _ long: Double) async {
let nowDate = Date.now
let oneDayFromDate = Date.now.addingTimeInterval(60 * 60 * 24)
do {
currentWeather = try await WeatherService.shared.weather(for: .init(latitude: lat, longitude: long), including: .current)
hourWeather = try await WeatherService.shared.weather(for: .init(latitude: lat, longitude: long), including: .hourly(startDate: nowDate, endDate: oneDayFromDate))
} catch {
print("WeatherKit failed to get: \(error)")
}
isLoading = false
}
var unwrappedTemperature: Double {
// Here: it's unwrapped
currentWeather?.temperature.value ?? 0
}
var unwrappedHourly: [HourWeather] {
hourWeather?.forecast ?? []
}
}
import SwiftUI
struct ContentView: View {
@EnvironmentObject private var weatherManager: WeatherManager
var body: some View {
VStack {
if !weatherManager.isLoading {
Text("\(weatherManager.unwrappedTemperature, specifier: "%.0f")°C")
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(weatherManager.unwrappedHourly, id: \.date) { hour in
// Here: is it possible to unwrap "temperature.value"?
Text("\(hour.temperature.value, specifier: "%.0f")°C")
}
}
}
} else {
ProgressView()
}
}
}
}
I hope my question is clear enough. Thanks, in advance!
WeatherKit
uses non-optional values as much as possible.A better approach is to create an enum for the loading state and set it accordingly. There are states for
idle
,loading
,loaded
passing the non-optional data andfailed
passing the error.And it's not necessary to call the service twice.
In the view
switch
on the state and show appropriate views