xcodeswiftuiweatherkit

Change weather icon with WeatherKit (SwiftUI)


Very new to SwiftUI. I'm working on a very simple weather app using Apple's WeatherKit. Have no problem getting the temperature and other parameters but I'd like to change the systemImage icon (sun, cloud, moon, etc...) to a corresponding emoji. Tried to create an enum with no luck:

import Foundation
import WeatherKit
import SwiftUI

@MainActor class WeatherKitManager: ObservableObject {

    @Published var weather: Weather?
    
    
    func getWeather() async {
        do {
            weather = try await Task.detached(priority: .userInitiated) {
                return try await WeatherService.shared.weather(for: .init(latitude: 42.28851, longitude: 13.55401))  // Coordinates for SAN PIO just as example coordinates
            }.value
        } catch {
            fatalError("\(error)")
        }
    }
    
    enum WeatherEmoji: String, Codable {
        case blowingDust = "blowingDust"
        case clear = "clear"
        case cloudy = "cloudy"
        case foggy = "foggy"
        case haze = "haze"
        case mostlyClear = "mostlyClear"
        case mostlyCloudy = "mostlyCloudy"
        case partlyCloudy = "partlyCloudy"
        case smokey = "smokey"
        case breezy = "breezy"
        case windy = "windy"
        case drizzle = "drizzle"
        case heavyRain = "heavyRain"
        case isolatedThunderstorms = "isolatedThunderstorms"
        case rain = "rain"
        case sunShowers = "sunShowers"
        case scatteredThunderstorms = "scatteredThunderstorms"
        case strongStorms = "strongStorms"
        case thunderstorms = "thunderstorms"
        case frigid = "frigid"
        case hail = "hail"
        case hot = "hot"
        case flurries = "flurries"
        case sleet = "sleet"
        case snow = "snow"
        case sunFlurries = "sunFlurries"
        case wintryMix = "wintryMix"
        case blizzard = "blizzard"
        case blowingSnow  = "blowingSnow"
        case freezingDrizzle = "freezingDrizzle"
        case freezingRain = "freezingRain"
        case heavySnow = "heavySnow"
        case hurricane = "hurricane"
        case tropicalStorm = "tropicalStorm"
        
        var emojiweather: LocalizedStringKey {
            
            switch self {
            case .clear:
                return "β˜€οΈ"
            case .blowingDust:
                return "πŸ’¨"
            case .cloudy:
                return "☁️"
            case .foggy:
                return "🌫️"
            case .haze:
                return "πŸ˜Άβ€πŸŒ«οΈ"
            case .mostlyClear:
                return "🌀️"
            case .mostlyCloudy:
                return "πŸŒ₯️"
            case .partlyCloudy:
                return "⛅️"
            case .smokey:
                return "πŸ˜Άβ€πŸŒ«οΈ"
            case .breezy:
                return "πŸ’¨"
            case .windy:
                return "πŸƒ"
            case .drizzle:
                return "β˜”οΈ"
            case .heavyRain:
                return "🌧️"
            case .isolatedThunderstorms:
                return "⚑️"
            case .rain:
                return "🌧️"
            case .sunShowers:
                return "🌀️"
            case .scatteredThunderstorms:
                return "⚑️"
            case .strongStorms:
                return "β›ˆοΈ"
            case .thunderstorms:
                return "β›ˆοΈ"
            case .frigid:
                return "🧣"
            case .hail:
                return "❄️"
            case .hot:
                return "πŸ”₯"
            case .flurries:
                return "πŸ’¨"
            case .sleet:
                return "🌨️"
            case .snow:
                return "β˜ƒοΈ"
            case .sunFlurries:
                return "🌀️"
            case .wintryMix:
                return "🧣"
            case .blizzard:
                return "🌨️"
            case .blowingSnow:
                return "🌨️"
            case .freezingDrizzle:
                return "πŸ₯Ά"
            case .freezingRain:
                return "🌧️"
            case .heavySnow:
                return "🌨️"
            case .hurricane:
                return "πŸŒͺ️"
            case .tropicalStorm:
                return "πŸŒͺ️"
            }
        }
    }
    
    var lookslikemoji: String {
        let myemoji = "\(WeatherEmoji.self)"
        return "\(myemoji)"
    }
    
    var symbol: String {
        weather?.currentWeather.symbolName ?? "xmark"
    }
    
    var temp: String {
        let temp = weather?.currentWeather.temperature
        
        let convert = temp?.converted(to: .celsius).formatted(.measurement(width: .narrow, usage: .asProvided, numberFormatStyle: .number.precision(.fractionLength(0))))
        return convert ?? "Loading Weather Data"
        
    }
    
    var feelslike: String {
        
        let feelslike = weather?.currentWeather.apparentTemperature
        
        let convert = feelslike?.converted(to: .celsius).formatted(.measurement(width: .narrow, usage: .asProvided, numberFormatStyle: .number.precision(.fractionLength(0))))
        return convert ?? "Loading Weather Data"
        
     } 
 }

What am I am doing wrong? Thank you.


Solution

  • A better way is to convert the WeatherCondition enum case which matches the symbol property

    1. Declare an extension of WeatherCondition with a computed property emoji

      extension WeatherCondition {
          var emoji : String {
              switch self {
      
              }
          }
      }
      
    2. The compiler will show a Switch must be exhaustive error. Click on the little red circle and then on Fix. This adds stubs for all cases.

    3. Return the corresponding emoji for each case for example

      case .blizzard: return "🌨️"
      case .blowingDust: return "πŸ’¨"
      ...
      
    4. In the view show the emoji with weather.condition.emoji