如何为每个小部件获取不同的数据

How to get different data for each widget

我正在阅读 WidgetBundle 并拥有多个小部件 - 在我的例子中,我想根据性别为用户提供两个不同的小部件。因此,用户可以选择查看 MensWomens

对于每个小部件,时间轴需要调用不同的 API - 执行此操作的最佳方法是什么?我看不到任何具有 WidgetBundle 并将时间线修改为 略微 的示例(它实际上是 api [=27 中的一个参数) =]).或者这是不可能的?

代码:

func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
// Call API here and get gifts
// I'd want to set "womens" or "mens" in the api url here depending on the widget

    let entry = WidgetTimelineEntry(date: Date(), gifts: gifts, widgetURL: widgetURL)
    let date = Calendar.current.date(byAdding: .minute, value: 30, to: Date())!
    let timeline = Timeline(entries: [entry], policy: TimelineReloadPolicy.after(date))
    completion(timeline)
}

...

struct WidgetTimelineEntry: TimelineEntry {
    let date: Date
    let gifts: [Product]
    let widgetURL: URL
}

struct GiftWidgetEntryView : View {
    @Environment(\.widgetFamily) private var widgetFamily
    var entry: Provider.Entry

    var body: some View {
        Group {
            if widgetFamily == .systemMedium {
                MediumWidgetView(gifts: entry.gifts)
            }
        }
        .widgetURL(entry.widgetURL)
    }
}

@main
struct GiftWidgets: WidgetBundle {
    @WidgetBundleBuilder
    var body: some Widget {

        // My widgets
        WomensWidget()
        MensWidget()
    }
}

struct WomensWidget: Widget {
    let kind: String = "WomensWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
        GiftWidgetEntryView(entry: entry)
    }
    .configurationDisplayName("Women's Gift Widget")
    .description("See some womens gift ideas")
    }
}

struct MensWidget: Widget {
    let kind: String = "MensWidget"

    var body: some WidgetConfiguration {
    StaticConfiguration(kind: kind, provider: Provider()) { entry in
        GiftWidgetEntryView(entry: entry)
    }
    .configurationDisplayName("Men's Gift Widget")
    .description("See some mens gift ideas")
    }
}

您可以将 gender 参数传递给 Provider 以便稍后在 getTimeline 函数中使用它:

enum Gender {
    case male, female // ...
}

struct Provider: TimelineProvider {
    let gender: Gender

    ...

    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        // Configure the API call based on the `gender` property
    
        let entry = WidgetTimelineEntry(date: Date(), gifts: gifts, widgetURL: widgetURL)
        let date = Calendar.current.date(byAdding: .minute, value: 30, to: Date())!
        let timeline = Timeline(entries: [entry], policy: TimelineReloadPolicy.after(date))
        completion(timeline)
    }
}

然后,你只需要将正确的参数传递给 Provider:

struct WomensWidget: Widget {
    let kind: String = "WomensWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider(gender: .female)) { entry in
            GiftWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Women's Gift Widget")
        .description("See some womens gift ideas")
    }
}

struct MensWidget: Widget {
    let kind: String = "MensWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider(gender: .male)) { entry in
            GiftWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Men's Gift Widget")
        .description("See some mens gift ideas")
    }
}