This project was built with the SwiftUI.
This app uses the OpenAPI library.
It also uses the first-party frameworks Charts, CoreLocation to serve clients
It is responsive and components are laid out with the user experience in mind.
This project allowed me to become a 'Contributor' to OpenMeteo/SDK.
I didn't do much, but it gave me the experience of creating and resolving an issue. open-meteo/sdk#66
- SwiftUI
- open-meteo Weather OpenAPI
- open-meteo Weather Library SDK
- SwiftUI AutoLayout
- Chart
- Pages with organized charts
- Chart Data Expression
- Swift Data Structure
- Peer Soft Skill
var body: some View {
Chart{
ForEach(weeklyData) { series in
ForEach(series.temperatureData, id: \.day) { data in
LineMark(
x: .value("Day", data.day, unit: .day),
y: .value("Temperature", data.temperature)
)
.foregroundStyle(by: .value("TemperatureType", series.temperatureType))
.symbol(by: .value("TemperatureType", series.temperatureType))
.interpolationMethod(.catmullRom)
}
}
if let selectedDate {
RuleMark(
x: .value("Selected", selectedDate, unit: .day)
)
.foregroundStyle(Color.gray.opacity(0.3))
.zIndex(1)
.annotation(
position: .top, spacing: 0,
overflowResolution: .init(
x: .fit(to: .chart),
y: .disabled
)
) {
valueSelectionPopover
}
}
}
.chartForegroundStyleScale { colorTemperature[$0]! }
.chartSymbolScale([
"Max Temperature": Circle().strokeBorder(lineWidth: 2),
"Min Temperature": Square().strokeBorder(lineWidth: 2)
])
.chartXAxis {
AxisMarks(values: .stride(by: .day)) { _ in
AxisTick()
AxisGridLine()
AxisValueLabel(format: .dateTime.weekday(.abbreviated), centered: true)
}
}
.chartXSelection(value: $rawSelectedDate)
}
// Mock data
static let weeklydata: [WeatherSeries] = [
.init(temperatureType: "Max Temperature", temperatureData: [
(day: date(year: 2022, month: 5, day: 2), temperature: Float(15.3)),
(day: date(year: 2022, month: 5, day: 3), temperature: Float(6.2)),
(day: date(year: 2022, month: 5, day: 4), temperature: Float(19.1)),
(day: date(year: 2022, month: 5, day: 5), temperature: Float(15.4)),
(day: date(year: 2022, month: 5, day: 6), temperature: Float(4.5)),
(day: date(year: 2022, month: 5, day: 7), temperature: Float(11)),
(day: date(year: 2022, month: 5, day: 8), temperature: Float(19.9))
]),
.init(temperatureType: "Min Temperature", temperatureData: [
(day: date(year: 2022, month: 5, day: 2), temperature: Float(5.3)),
(day: date(year: 2022, month: 5, day: 3), temperature: Float(-6.2)),
(day: date(year: 2022, month: 5, day: 4), temperature: Float(9.1)),
(day: date(year: 2022, month: 5, day: 5), temperature: Float(-15.4)),
(day: date(year: 2022, month: 5, day: 6), temperature: Float(-4.5)),
(day: date(year: 2022, month: 5, day: 7), temperature: Float(-11)),
(day: date(year: 2022, month: 5, day: 8), temperature: Float(9.9))
]),
]
// Transformation Code
private func prepareWeeklyData() -> [WeeklyWeatherData.WeatherSeries] {
guard let weatherData = weatherManager.weatherData else { return [] }
let maxTemperatureSeries = WeeklyWeatherData.WeatherSeries(
temperatureType: "Max Temperature",
temperatureData: weatherData.daily.time.indices.map { index in
(day: weatherData.daily.time[index], temperature: weatherData.daily.temperature2mMax[index])
}
)
let minTemperatureSeries = WeeklyWeatherData.WeatherSeries(
temperatureType: "Min Temperature",
temperatureData: weatherData.daily.time.indices.map { index in
(day: weatherData.daily.time[index], temperature: weatherData.daily.temperature2mMin[index])
}
)
return [maxTemperatureSeries, minTemperatureSeries]
}