Dow do I use WeatherKit Swift framework to fetch the weather inside a Widget Extension?

I can't fetch the weather using the WeatherKit framework inside a Widget Extension.

Here's a project I created just for this example. This widget shows the humidity of a sample location.

Here's the code:

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

It works fine in the simulator:

But it doesn't work in a real device. As soon as I call WeatherService's weather(for: CLLocation) async throws -> Weather the widget get's "blocked":

I've tried moving the try await WeatherService.shared.weather(for: sampleLocation) to different places, but nothing worked. As soon as I comment out this line (and create an entry with a placeholder humidity) everything works.

I added the WeatherKit capability in the main app target and in the WidgetExtension target. I also added the WeatherKit "Capability" and "App Service" in the "Certificates, Identifiers & Profiles" of the Apple Developer website.

The WeatherKit framework works fine in other parts of the main app.

I haven't tried using the WeatherKit REST API, yet.

Any ideas what could be happening?

Accepted Reply

Got it! Apple Developer portal automatically created an "Identifier" for my WidgetExtension, that's separate from the main app Identifier. I had no idea that's how this worked, I thought I had to create them manually. I added WeatherKit as an AppService there and it worked.

Replies

Got it! Apple Developer portal automatically created an "Identifier" for my WidgetExtension, that's separate from the main app Identifier. I had no idea that's how this worked, I thought I had to create them manually. I added WeatherKit as an AppService there and it worked.

I had the same problem, but I solved it with your post! Thank you very much!

Hi,

how to change from 0.88 into 88% ? I am looking for the modifier but cannot find it .humidity.( ?)

any help will be very appreciated thanks S.