IntentHandler не работает с widgetFamily

Я добавил в свой проект Intent Extension Target и пытаюсь определить, какой тип виджета отображается в режиме редактирования в IntentHandler, и на основе этой информации я хочу заполнить список Edit Widget маленькими, средними или большими типами виджетов.

Когда я использую @Environment(\.widgetFamily) var family, это дает мне .systemMedium все время, но в это время я редактирую виджет большого размера.

Например, Когда я долго нажимаю на маленький виджет для редактирования и выбора другого типа виджета из списка, я вижу список, полный элементов, содержащих малые, средние и большие типы виджетов из IntentHandler, но я хочу видеть только мелкие типы.

Вопрос в том, можно ли заполнить список в зависимости от того, какой тип виджета я сейчас редактирую?


person serdaryillar    schedule 25.12.2020    source источник
comment
Не могли бы вы поделиться своим кодом IntentHandler? Он должен быть в вашем основном приложении или в расширении Intent; Такие элементы SwiftUI, как @Environment(\.widgetFamily), не будут работать вне кода вашего виджета.   -  person Adam    schedule 26.12.2020


Ответы (1)


Если я понимаю, что вы пытаетесь сделать, думаю, ответ - нет, это невозможно. Чтобы повторить то, что делают такие приложения, как Widgetsmith, вам нужно определить 3 отдельных виджета, по одному для каждого supportedFamily размера малого, среднего и большого. Затем определите 3 отдельных намерения, по одному для каждого виджета, и реализуйте отдельный обработчик намерений для каждого из них.

Что-то вроде этого:

@main
struct MyWidgetBundle: WidgetBundle {
    @WidgetBundleBuilder
    var body: some Widget {
        SmallWidget()
        MediumWidget()
        LargeWidget()
    }
}

struct SmallWidget: Widget {
    let kind: String = "SmallWidget"
    
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: SmallWidgetIntent.self, provider: TimelineProvider()) { entry in
            WidgetView(entry: entry)
        }
        .configurationDisplayName("Small Widget")
        .supportedFamilies([.systemSmall])
    }
}

struct MediumWidget: Widget {
    let kind: String = "MediumWidget"
    
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: MediumWidgetIntent.self, provider: TimelineProvider()) { entry in
            WidgetView(entry: entry)
        }
        .configurationDisplayName("Medium Widget")
        .supportedFamilies([.systemMedium])
    }
}

struct LargeWidget: Widget {
    let kind: String = "LargeWidget"
    
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: LargeWidgetIntent.self, provider: TimelineProvider()) { entry in
            WidgetView(entry: entry)
        }
        .configurationDisplayName("Large Widget")
        .supportedFamilies([.systemLarge])
    }
}

В вашем файле определения намерения определите SmallWidgetIntent, MediumWidgetIntent и LargeWidgetIntent. А затем в обработчике намерений вы реализуете SmallWidgetIntentHandling, MediumWidgetIntentHandling и LargeWidgetIntentHandling, которые вернут правильные параметры для соответствующего размера.

person Adam    schedule 26.12.2020
comment
Спасибо, Адам! Как вы упомянули, я разделил его на 3 разных виджета и объединил их с помощью WidgetBuilder. Теперь у меня есть единственный класс IntentHandler, соответствующий 3 IntentHandling. Это работает!!! Спасибо еще раз! - person serdaryillar; 28.12.2020
comment
Также необходимо создать отдельные TimelineProvider для каждой семьи? - person iOS Dev; 16.06.2021
comment
@iOS Dev Вы можете использовать один и тот же TimelineProvider для всех своих виджетов. - person Adam; 16.06.2021
comment
@Adam Но в моем пользовательском IntentTimelineProvider я должен установить типалиас Intent, но у меня есть 3 разных намерения, как вы предложили. - person iOS Dev; 17.06.2021
comment
@iodev Вы правы, извините, я неправильно это понял. Вам нужны отдельные IntentTimelineProvider для каждого Intent. - person Adam; 17.06.2021