如何使用 Wea​​therKit Swift 框架在小部件扩展中获取天气?

2023-12-10

我无法使用小组件扩展中的 WeatherKit 框架获取天气。

这是我为本示例创建的一个项目。该小部件显示样本位置的湿度。

这是代码:

import WidgetKit
import SwiftUI
import WeatherKit
import CoreLocation

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(), humidity: 9.99) // placeholder humidity
    }

    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date(), humidity: 9.99) // placeholder humidity
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        Task {
            let nextUpdate = Date().addingTimeInterval(3600) // 1 hour in seconds
            
            let sampleLocation = CLLocation(latitude: 51.5072, longitude: 0.1276) // sample location (London)
            let weather = try await WeatherService.shared.weather(for: sampleLocation)
            let entry = SimpleEntry(date: .now, humidity: weather.currentWeather.humidity)
            
            let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
            completion(timeline)
        }
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let humidity: Double
}

struct WidgetWeatherTestWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        Text("\(entry.humidity)")
    }
}

struct WidgetWeatherTestWidget: Widget {
    let kind: String = "WidgetWeatherTest"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            WidgetWeatherTestWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Widget Weather Test")
        .description("Testing weatherkit in a Widget")
        .supportedFamilies([.systemMedium])
    }
}

它在模拟器中运行良好:

enter image description here

但它在真实设备中不起作用。我一打电话WeatherService's weather(for: CLLocation) async throws -> Weather小部件被“阻止”。

blocked widget

我试过移动try await WeatherService.shared.weather(for: sampleLocation)去了不同的地方,但没有任何效果。一旦我注释掉这一行(并创建一个带有占位符湿度的条目),一切就正常了。

我在主应用程序目标和 WidgetExtension 目标中添加了 WeatherKit 功能。我还在Apple开发者网站的“Certificates, Identifiers & Profiles”中添加了WeatherKit“Capability”和“App Service”。

WeatherKit 框架在主应用程序的其他部分运行良好。

我还没有尝试过使用 Wea​​therKit REST API。

有什么想法可能会发生什么吗?


您应该将您的条目设置为使用Result,这样您就可以直观地看到正在发生的任何错误。

struct SimpleEntry: TimelineEntry {
    let date: Date
    let configuration: ConfigurationIntent
    let result: Result<any CurrentWeatherProtocol, Error>
}

然后在视图中您可以显示错误或天气视图。

struct PWCWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        Text(entry.date, style: .time)
        switch entry.result{
        case .success(let weather):
            Image(systemName: weather.symbolName)
        case .failure(let error):
         
            Text(error.localizedDescription)

            let nserror = error as NSError
            Text(nserror.userInfo.description)

            Text("\(error)")
        }
    }
}

我的整个代码库是一个更复杂的项目的一部分,但这就是getTimeline好像。

func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
    Task{
        let now = Date.now
        let inHr = Calendar.current.date(byAdding: .hour, value: 1, to: now)!
        do{
            
            let location = try await locSvc.requestSingleLocation()
            let wSvc = try await CDWeatherService().currentWeather(for: WeatherEntry(location: .init(location: location)))
            //Return a successful result
            let entry = SimpleEntry(date: now, configuration: configuration, result: .success(wSvc))
            let timeline = Timeline(entries: [entry], policy: .after(inHr))
            completion(timeline)
        }catch{
            //Return a failure result
            let entry = SimpleEntry(date: now, configuration: configuration, result: .failure(error))
            let timeline = Timeline(entries: [entry], policy: .after(inHr))
            completion(timeline)
        }
    }
}

我发现 macOS 和 iOS Widget 扩展是我的问题,你必须确保选择正确的一个。

另外,请确保您已将“WeatherKit”添加到小部件扩展的“签名和功能”中。

WeatherDaemon.WDSJWTAuthenticatorServiceListener.Errors 错误 2。

与 AppStore Connect 中的“应用程序服务”中未包含 Weather Kit 有关,它必须包含在 App Store Connect - 小部件标识符 - 功能

App Store Connect - 小部件标识符 - AppServices

Xcode 中应用程序和/或小部件的签名和功能

enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Wea​​therKit Swift 框架在小部件扩展中获取天气? 的相关文章

随机推荐