Skip to content

Latest commit

 

History

History
130 lines (110 loc) · 5.64 KB

File metadata and controls

130 lines (110 loc) · 5.64 KB

Weather Cast App

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


What I learned

image image
image image
image image
Simulator Screen Recording - iPhone 15 - 2024-03-11 at 19 44 24

A quick look at SWIFT code

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]
    }