3 января 2023 г. | Разработка | Ли Ках Сенг

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

Apple предоставила нам 2 способа включить поддержку нескольких виджетов в наших приложениях:

  • Использование бандл виджетов.

  • Наличие нескольких расширений виджета.

В этой статье мы рассмотрим оба этих метода по отдельности, так что давайте начнем.

ПримечаниеЕсли вы не знакомы с тем, как создать виджет с помощью WidgetKit, я настоятельно рекомендую вам сначала прочитать мою статью «Начало работы с WidgetKit», прежде чем продолжить.

# 1: Использование Бандл Виджетов

Допустим, мы реализовали виджет с именем MyWidget1.

@main
struct MyWidget1: Widget {

    var body: some WidgetConfiguration {
        // Widget configuration here...
        // ...
        // ...
    }
}

Поскольку MyWidget1 был снабжен атрибутом @main, система примет его за точку входа расширения виджета и отобразит снимок виджета в галерее виджетов.

Теперь предположим, что мы создали другой виджет с именем MyWidget2 в том же расширении виджета. Если мы попытаемся отметить MyWidget2 атрибутом @main, мы получим сообщение об ошибке компиляции:

атрибут 'main' может применяться только к одному типу в модуле.

По существу, эта ошибка означает, что у нас не может быть 2 точек входа в одном и том же расширении виджета. Итак, что мы должны сделать, чтобы MyWidget1 и MyWidget2 могли появиться в галерее виджетов? Здесь на помощь приходит Widget Bundle.

Вот как использовать бандл виджетов:

@main
struct MyWidgetBundle: WidgetBundle {
    
    @WidgetBundleBuilder
    var body: some Widget {
        MyWidget1()
        MyWidget2()
    }
}

Как видите, способ использования бандла виджетов довольно прост. Все, что нам нужно сделать, это аннотировать его атрибутом @main и сделать MyWidget1 и MyWidget2 частью его тела. Не забудьте также удалить аннотацию @main в MyWidget1.

Обратите внимание, что в галерее виджетов будут отображаться виджеты в соответствии с порядком расположения виджетов в теле бандла виджетов.

Выходя за Пределы Бандла Виджетов

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

Если мы попытаемся добавить более 10 виджетов в тело бандла виджетов, мы получим ошибку компиляции «Extra argument in call» (Избыточный аргумент в вызове).

@main
struct MyWidgetBundle: WidgetBundle {
    
    @WidgetBundleBuilder
    var body: some Widget {
        MyWidget1()
        MyWidget2()
        MyWidget3()
        MyWidget4()
        MyWidget5()
        MyWidget6()
        MyWidget7()
        MyWidget8()
        MyWidget9()
        MyWidget10()
        MyWidget11() // ???? Error: Extra argument in call
    }
}

Чтобы обойти такое ограничение, все, что нам нужно сделать, это создать еще один бандл и добавить его тело в тело первого бандла виджетов.

@main
struct MyWidgetBundle: WidgetBundle {
    
    @WidgetBundleBuilder
    var body: some Widget {
        MyWidget1()
        MyWidget2()
        MyWidget3()
        MyWidget4()
        MyWidget5()
        MyWidget6()
        MyWidget7()
        MyWidget8()
        MyWidget9()
        AnotherWidgetBundle().body
    }
}


struct AnotherWidgetBundle: WidgetBundle {

    @WidgetBundleBuilder
    var body: some Widget {
        MyWidget10()
        MyWidget11()
    }
}

Теоретически это должно позволить нам поддерживать неограниченное количество виджетов в Xcode. Однако я не уверен, есть ли ограничение на количество виджетов, разрешенных в галерее виджетов, если вы знаете ответ, пожалуйста, дайте мне знать.

# 2: Наличие нескольких расширений виджета

Помимо использования бандлов виджетов, еще одним способом поддержки нескольких виджетов является наличие нескольких расширений виджетов. По словам Apple, такой способ следует использовать только в очень специфической ситуации.

Допустим, у нас есть приложение с несколькими виджетами, и только некоторым из них требуется служба определения местоположения. В этом случае мы можем разделить эти виджеты на несколько расширений. Это позволяет системе запрашивать у пользователя только те виджеты, которые используют службу определения местоположения.

Вы можете узнать больше о том, как добавить расширение виджета здесь.

Вот и все!

Спасибо за прочтение. ????????‍????

Комментарии (0)