You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WeatherKit扩展switch匹配天气状态失效,始终返回默认值问题

问题:天气APP背景视频无法根据天气条件切换

我正在开发一款简易天气APP,希望根据不同天气状况(晴、雨、雪等)设置不同的背景视频。已实现视频在View中循环播放,但无法根据天气条件切换。视频存储在Bundle中,以字符串名称("deer"、"lake"、"snow")调用。

已实现的代码

WeatherCondition扩展

extension WeatherCondition {
    var videoBG : String {
        switch self {
            
        case .blizzard:
            return "snow"
        case .blowingDust:
            return "lake"
        case .blowingSnow:
            return "lake"
        case .breezy:
            return "lake"
        case .clear:
            return "deer"
        case .cloudy:
            return "lake"
        case .drizzle:
            return "lake"
        case .flurries:
            return "lake"
        case .foggy:
            return "lake"
        case .freezingDrizzle:
            return "lake"
        case .freezingRain:
            return "lake"
        case .frigid:
            return "lake"
        case .hail:
            return "lake"
        case .haze:
            return "lake"
        case .heavyRain:
            return "lake"
        case .heavySnow:
            return "lake"
        case .hot:
            return "lake"
        case .hurricane:
            return "lake"
        case .isolatedThunderstorms:
            return "lake"
        case .mostlyClear:
            return "deer"
        case .mostlyCloudy:
            return "lake"
        case .partlyCloudy:
            return "lake"
        case .rain:
            return "lake"
        case .scatteredThunderstorms:
            return "lake"
        case .sleet:
            return "lake"
        case .smoky:
            return "lake"
        case .snow:
            return "lake"
        case .strongStorms:
            return "lake"
        case .sunFlurries:
            return "lake"
        case .sunShowers:
            return "lake"
        case .thunderstorms:
            return "deer"
        case .tropicalStorm:
            return "lake"
        case .windy:
            return "lake"
        case .wintryMix:
            return "lake"
        @unknown default:
            return "deer"
        }
    }
}

WeatherKitManager实现

@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.34779, longitude: 13.39943))  // 示例坐标
            }.value
        } catch {
            fatalError("\(error)")
        }
    }

    var videoAppBG: String {
        weather?.currentWeather.condition.videoBG ?? "snow"
    }
}

View中的背景设置

var body: some View {
    
    NavigationView {
        ZStack {
            
            BgdFullScreenVideoView(videoName: weatherKitManager.videoAppBG)
                .zIndex(-10)
            VStack (alignment: .leading, spacing: 10) {
                Spacer()
                VStack(alignment: .leading) {
                    Text("\(weatherKitManager.temp)")
                        .foregroundColor(.white)
                        .font(.system(size: 75))
                        .fontWeight(.black)
                        .shadow(radius: 8)
                    
                    Text("L'Aquila")
                        .foregroundColor(.white)
                        .font(.system(size: 30))
                        .fontWeight(.medium)
                        .shadow(radius: 8)
                }
                .padding(.bottom, 80)
            }
            .padding(.leading,25)
            .frame(maxWidth: .infinity, alignment: .leading)
            
        }
        .toolbar {
            ToolbarItem(placement: .navigationBarLeading) {
                ZStack {
                    Image("logo")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 30, height: 30)
                        .shadow(radius: 3)
                        .zIndex(10)
                }
                .padding(.top,40)
            }
        }
    }
    .onAppear() {
        Task {
            await weatherKitManager.getWeather()
        }
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .ignoresSafeArea()
}

问题现象

无论实际天气如何,始终播放"snow"视频。使用相同方式获取温度、symbolName等属性均正常工作,说明weather对象是正常获取的,但videoAppBG始终返回默认值。

解决方案

核心问题是videoAppBG是普通计算属性,不会随着weather的更新自动触发视图刷新。虽然weather是@Published属性,但视图不会监听计算属性的变化,导致它一直停留在初始的默认值"snow"。

方案一:直接在View中访问目标属性(推荐)

修改View中的视频视图参数,跳过中间的videoAppBG属性,直接通过weather对象获取视频名称:

BgdFullScreenVideoView(videoName: weatherKitManager.weather?.currentWeather.condition.videoBG ?? "snow")

这样当weather更新时,视图会自动读取最新的condition.videoBG值,触发视频切换。

方案二:同步更新@Published属性(可选)

如果想保留videoAppBG属性,可以将其改为@Published,并在获取到天气后手动更新:

@MainActor class WeatherKitManager: ObservableObject {
    
    @Published var weather: Weather?
    @Published var videoAppBG: String = "snow" // 改为@Published
    
    func getWeather() async {
        do {
            weather = try await Task.detached(priority: .userInitiated) {
                return try await WeatherService.shared.weather(for: .init(latitude: 42.34779, longitude: 13.39943))
            }.value
            // 获取天气后同步更新videoAppBG
            videoAppBG = weather?.currentWeather.condition.videoBG ?? "snow"
        } catch {
            fatalError("\(error)")
        }
    }
}

此方案需要手动维护属性同步,不如方案一简洁。

内容的提问来源于stack exchange,提问作者helloimbrando

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 21:55:15