Tehnografi.com - Технологические новости, обзоры и советы

Объяснение делегата сцены и делегата приложения

Следующая статья поможет вам: Объяснение делегата сцены и делегата приложения

Вернуться в блог

Что делает класс SceneDelegate в вашем проекте iOS? В Xcode делегат сцены и/или делегат приложения добавляется автоматически для шаблона проекта приложения iOS по умолчанию. Для чего именно нужны эти делегаты?

В этом уроке мы углубимся в делегаты сцены и приложения в Xcode, а также в то, как они влияют на SwiftUI, раскадровки и пользовательские интерфейсы на основе XIB.

Вы узнаете о:

  • Делегат приложения и делегат сцены
  • Как они работают вместе при загрузке вашего приложения
  • Как настроить приложение программно с помощью делегата сцены
  • Использование делегата сцены с раскадровками и SwiftUI

Вероятно, вы уже знакомы с делегатом приложения. Это отправная точка для приложения iOS. Его функция application(_:didFinishLaunchingWithOptions:) — это первая функция, которую операционная система вызывает при запуске вашего приложения.

Класс AppDelegate вашего приложения использует протокол UIApplicationDelegate, который является частью платформы UIKit. Как мы скоро обнаружим, роль делегата приложения изменилась с iOS 12.

Вот для чего вы обычно использовали делегат приложения:

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

Шаблонное приложение, использующее раскадровки, имеет на удивление скучный делегат приложения, поскольку он возвращает только true. Так:

func application (_ application: UIApplication, DidFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Бул
{
вернуть истину
}

Простое приложение, которое использует XIB и, следовательно, настраивает собственный контроллер корневого представления, выглядит примерно так:

func application (_ application: UIApplication, DidFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Бул

{
пусть временная шкала = TimelineViewController()
пусть навигация = UINavigationController (rootViewController: временная шкала)

пусть кадр = UIScreen.main.bounds
окно = UIWindow (кадр: кадр)

окно!.rootViewController = навигация
окно!.makeKeyAndVisible()

вернуть истину
}

Почему функция application(_:didFinishLaunchingWithOptions:) возвращает true? Это логическое значение указывает, что приложение можно запустить на основе параметров, переданных функции. Обычно возвращается true, но вы также можете вернуть false, если приложение не может запуститься из-за какого-либо URL-ресурса или активности пользователя.

В приведенном выше коде мы создаем контроллер представления, помещаем его в контроллер навигации и присваиваем его свойству rootViewController объекта UIWindow. Этот объект окна является свойством делегата приложения, и это единственное окно, которое есть в нашем приложении.

Окно приложения — важная концепция. По сути, окно — это приложение, а приложения iOS имеют только одно окно (пока). В этом окне размещаются пользовательские интерфейсы вашего приложения, отправляются события в представления и обеспечивается основной фон для отображения содержимого вашего приложения. В некотором смысле, концепция «windows»- это то, что Microsoft Windows назван в честь — вы знаете, — и на iOS эта концепция ничем не отличается. (Спасибо, Ксерокс!)

Хорошо, теперь, когда с этим покончено, давайте перейдем к делегату сцены.

Если понятие «окна» неясно, воспользуйтесь переключателем приложений на своем iPhone. Дважды нажмите кнопку «Домой» или проведите пальцем вверх от нижней части iPhone и вуаля, вы увидите windows приложений, которые в данный момент работают. Этот пользовательский интерфейс называется переключателем приложений.

В iOS 13 (и более поздних версиях) делегат сцены берет на себя некоторые роли делегата приложения. Самое главное, что концепция окна заменяется (более или менее) концепцией сцены. Приложение может иметь более одной сцены, и теперь сцена служит фоном для пользовательских интерфейсов и контента вашего приложения.

Особенно интересна концепция наличия одного приложения с несколькими сценами, поскольку она позволяет создавать многооконные приложения на iOS и iPadOS. Например, каждый текстовый документ в приложении текстового процессора может иметь свою собственную сцену. Пользователи также могут создать копию сцены, эффективно запуская несколько экземпляров одного приложения одновременно.

На практике использование делегата сцены наиболее заметно в Xcode в трёх местах:

  1. В новом проекте iOS есть класс SceneDelegate, который автоматически создается для проекта приложения по умолчанию и включает в себя знакомые события жизненного цикла, такие как активация, отставка и отключение.
  2. Класс AppDelegate имеет две новые функции, связанные с сеансами сцены: application(_:configurationForConnecting:options:) и application(_:didDiscardSceneSessions:).
  3. Список свойств Info.plist получает манифест сцены приложения, в котором перечислены сцены, являющиеся частью этого приложения, включая имена их классов, делегатов и раскадровки.

Давайте рассмотрим их один за другим.

  1. Класс делегата сцены
  2. Прежде всего, класс SceneDelegate:

    Самая важная функция делегата сцены — это Scene(_:willConnectTo:options:). В каком-то смысле это больше всего похоже на роль функции application(_:didFinishLaunchingWithOptions:) делегата приложения. Эта функция вызывается при добавлении сцены в приложение, поэтому это идеальный момент для настройки этой сцены. В приведенном выше коде мы вручную настраиваем стек контроллера представления, но об этом позже.

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

    SceneDelegate также имеет следующие функции:

    • SceneDidDisconnect(_:) вызывается, когда сцена отключена от приложения (Note что он может повторно подключиться позже.)
    • SceneDidBecomeActive(_:) вызывается, когда пользователь начинает взаимодействовать со сценой, например, выбирая ее в переключателе приложений.
    • SceneWillResignActive(_:) вызывается, когда пользователь прекращает взаимодействие со сценой, например, переключаясь на другую сцену.
    • SceneWillEnterForeground(_:) вызывается, когда сцена выходит на передний план, т.е. начинается или возобновляется из фонового состояния.
    • SceneDidEnterBackground(_:) вызывается, когда сцена переходит в фоновый режим, т. е. приложение свернуто, но все еще присутствует в фоновом режиме.

    Видите симметрию между этими функциями? Активный/неактивный, фоновый/передний план и «отключение». Это типичные события жизненного цикла любого приложения или процесса.

  3. Делегат приложения: сеансы сцен
  4. Начиная с iOS 13, класс AppDelegate теперь включает еще две функции делегата, связанные с управлением сеансами сцены. Когда в вашем приложении создается сцена, объект сеанса сцены отслеживает всю информацию, связанную с этой сценой.

    Эти функции:

    • application(_:configurationForConnecting:options:), которому необходимо вернуть объект конфигурации при создании новой сцены
    • application(_:didDiscardSceneSessions:), который вызывается, когда пользователь вашего приложения закрывает одну или несколько сцен с помощью переключателя приложений.

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

    Приложение(_:didDiscardSceneSessions:) довольно простое. Он вызывается, когда пользователь вашего приложения закрывает одну или несколько сцен с помощью переключателя приложений. Вы можете использовать эту функцию, чтобы избавиться от ресурсов, которые использовали эти сцены, поскольку они больше не нужны.

    Важно противопоставить эту функцию сценеDidDisconnect(_:), которая вызывается просто при отключении сцены, но не обязательно отбрасывается. Он может повторно подключиться, тогда как application(_:didDiscardSceneSessions:) отмечает момент выхода из сцены с помощью переключателя приложений.

  5. Манифест сцены приложения Info.plist
  6. Каждую сцену, которую поддерживает ваше приложение, необходимо объявить в манифесте сцены приложения. Короче говоря, в манифесте перечислены все сцены, которые поддерживает ваше приложение. В большинстве приложений есть только одна сцена, но вы можете создать больше, например отдельные сцены для ответа на push-уведомления или определенных действий.

    Манифест манифеста сцены приложения является частью файла Info.plist, который является хорошо известным местом для значений конфигурации вашего приложения. Этот список свойств включает такие значения, как имя вашего приложения, версия, поддерживаемые ориентации интерфейса, а теперь и различные сцены, которые оно поддерживает.

    Здесь важно отметить, что вы объявляете типы сеансов, а не сами сеансы как таковые. Ваше приложение может поддерживать одну сцену, создавать копии этой сцены и использовать ее для создания многооконного приложения.

Вот обзор манифеста как части Info.plist:

На верхнем уровне вы видите запись манифеста сцены приложения. Под ним запись «Включить несколько». Windowsдля которого необходимо установить значение YES для поддержки нескольких windows. Ниже этого массива роль сеанса приложения используется для объявления сцен внутри приложения. Еще один пункт можно использовать для объявления сцен для внешних экранов.

Самая важная информация хранится внутри элементов массива ролей сеанса приложения. В этой записи перечислено следующее:

  • Имя этой конфигурации, которое должно быть уникальным.
  • Имя класса сцены, UIWindowScene.
  • Имя класса делегата для этой сцены, обычно SceneDelegate.
  • Имя раскадровки, содержащей исходный пользовательский интерфейс для этой сцены.

Этот элемент имени раскадровки может напоминать вам о настройке основного интерфейса, которую можно найти в конфигурации свойств проекта проекта Xcode. В базовом приложении для iOS, если вы не используете сцены, именно здесь вы сейчас можете установить или изменить основную раскадровку.

Как SceneDelegate, сеансы сцены в AppDelegate и манифест сцены приложения взаимодействуют друг с другом при создании многооконных приложений?

  • Сначала мы рассмотрели класс SceneDelegate. Он управляет жизненным циклом сцен, реагируя на такие события, как SceneDidBecomeActive(_:) и SceneDidEnterBackground(_:).
  • Затем мы проверили новые функции в классе AppDelegate. Он управляет сеансами сцен, предоставляет данные конфигурации для сцен и реагирует на удаление пользователем сцены.
  • Наконец, мы рассмотрели манифест сцены приложения. В нем перечислены сцены, которые поддерживает ваше приложение, и они соединяются с классом делегата и исходной раскадровкой.

Потрясающий! Теперь, когда у нас есть игровое поле, давайте выясним, как сцены влияют на создание пользовательских интерфейсов в Xcode.

В дальнейшем самый простой способ загрузить приложение iOS — использовать SwiftUI. Короче говоря, приложение SwiftUI в основном использует SceneDelegate для настройки исходного пользовательского интерфейса приложения.

Во-первых, вот как выглядит манифест сцены приложения:

Вы создаете приложение, основанное преимущественно на SwiftUI? Возможно, имеет смысл использовать настройку приложения SwiftUI для жизненного цикла приложения при создании приложения. Это добавит в ваше приложение реализацию протокола приложения, которая станет отправной точкой вашего приложения SwiftUI. Узнайте больше здесь: Объяснение жизненного цикла приложения SwiftUI.

Это довольно стандартно для приложения по умолчанию. Что примечательно, так это то, что в конфигурации по умолчанию не установлено имя раскадровки. Помните: если вы хотите поддерживать несколько windowsвам нужно будет установить Включить несколько Windows на ДА.

Мы собираемся пропустить AppDelegate, поскольку он довольно стандартен — в этом сценарии он вернет только true. Очень просто.

Далее класс SceneDelegate. Как мы уже обсуждали ранее, делегат сцены отвечает за настройку сцен вашего приложения, а также за настройку их начальных представлений.

Так:

класс SceneDelegate: UIResponder, UIWindowSceneDelegate {

окно вар: UIWindow?

func Scene (_ сцена: UIScene, сеанс willConnectTo: UISceneSession, параметры ConnectionOptions: UIScene.ConnectionOptions) {

пусть contentView = ContentView()

если пусть windowScene = сцена как? UIWindowScene {
пусть окно = UIWindow (windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = окно
окно.makeKeyAndVisible()
}
}

Что происходит в приведенном выше коде?

  • Во-первых, важно учитывать, что функция делегата Scene(_:willConnectTo:options:) вызывается при добавлении новой сцены в приложение. Ему предоставляется объект сцены (и сеанс). Этот объект UIWindowScene создается приложением, поэтому вы не делаете это вручную.
  • Затем также используется свойство window. Приложения по-прежнему используют объекты UIWindow, но теперь они являются частью сцены. В коде внутри блока if let вы можете ясно увидеть, как объект UIWindow инициализируется с использованием сцены.
  • Назначается корневой контроллер представления, локальная константа окна присваивается свойству window, а окно становится «ключевым и видимым», т. е. помещается в начало пользовательского интерфейса приложения.
  • Специально для SwiftUI создается ContentView и добавляется в качестве контроллера корневого представления с помощью UIHostingController. Этот контроллер используется для вывода на экран представлений на основе SwiftUI.
  • И последнее, но не менее важное: стоит отметить, что параметр сцены типа UIScene на самом деле является объектом типа UIWindowScene. Вот какой необязательный кастинг с каким? для. (До сих пор создаваемые сцены обычно имели тип UIWindowScene, но я предполагаю, что в будущем мы увидим больше типов сцен.)

Все это может показаться сложным, но при общем обзоре все довольно просто:

  • Делегат сцены настраивает сцену в нужный момент при вызове Scene(_:willConnectTo:options:).
  • Делегат приложения и манифест имеют конфигурацию по умолчанию, которая не включает раскадровку.
  • Функция Scene(_:willConnectTo:options:) создает представление SwiftUI, помещает его в хост-контроллер, назначает его корневому контроллеру представления свойства окна и помещает это окно в переднюю часть пользовательского интерфейса приложения.

Потрясающий! Давайте двигаться дальше.

Вы можете настроить базовый проект Xcode с помощью SwiftUI, выбрав «Файл» → «Создать» → «Проект…». Затем выберите «Приложение Single View». Наконец, выберите SwiftUI для пользовательского интерфейса. Узнайте больше здесь: Как создать новый проект приложения Xcode.

Раскадровки, наряду с XIB, являются эффективным способом создания пользовательского интерфейса для ваших приложений iOS. В будущем мы увидим больше приложений SwiftUI, но на данный момент раскадровки все еще довольно распространены.

Интересно, что вам не нужно ничего делать для создания нового проекта iOS в Xcode с помощью раскадровки, что касается нового делегата сцены. Просто выберите «Файл» → «Создать» → «Проект…». Затем выберите «Приложение Single View». Наконец, выберите «Раскадровка для пользовательского интерфейса», и все готово.

Вот как это настроено:

  • Как объяснялось ранее, вы найдете основную раскадровку в манифесте сцены приложения внутри Info.plist.
  • Делегат приложения по умолчанию будет использовать конфигурацию сцены по умолчанию.
  • Делегат сцены по умолчанию устанавливает объект UIWindow и использует Main.storyboard для создания исходного пользовательского интерфейса.

Вот и все. Действительно короткая глава, эта…

Многие разработчики создают свои пользовательские интерфейсы программным способом, и с появлением SwiftUI мы увидим еще больше этого. Что, если вы не используете раскадровки, а используете отдельные XIB для создания пользовательского интерфейса вашего приложения? Давайте проверим, какое место здесь занимает делегат сцены.

Во-первых, делегат приложения и манифест сцены приложения точно такие, как и следовало ожидать: установлены значения по умолчанию. Мы не используем раскадровку, вместо этого мы собираемся настроить начальный контроллер представления в функции Scene(_:willConnectTo:options:) внутри класса SceneDelegate.

Так:

класс SceneDelegate: UIResponder, UIWindowSceneDelegate {

окно вар: UIWindow?

сцена func (_ сцена: UIScene, сеанс willConnectTo: UISceneSession, параметры ConnectionOptions: UIScene.ConnectionOptions)
{
если пусть windowScene = сцена как? UIWindowScene {

пусть окно = UIWindow (windowScene: windowScene)
пусть временная шкала = TimelineViewController()

пусть навигация = UINavigationController (rootViewController: временная шкала)
window.rootViewController = навигация

self.window = окно
окно.makeKeyAndVisible()
}
}

Вот что происходит:

  • Как и раньше, у нас есть свойство окна типа UIWindow. Он инициализируется с помощью объекта windowScene, тип которого приведен из параметра сцены.
  • Внутри блока if let появляется знакомый код: именно так вы настроили контроллер корневого представления в iOS 12 и более ранних версиях с делегатом приложения. Вы инициализируете контроллер представления, помещаете его в контроллер навигации и назначаете его свойству rootViewController.
  • Наконец, локальная константа окна присваивается свойству window, и окно становится «ключевым и видимым», т. е. помещается на экран спереди.

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

Хотите добавить поддержку сцен в существующий проект приложения iOS? Ознакомьтесь с этими инструкциями.

Пффф! Это довольно большая работа для такого простого компонента. Как мы уже говорили, делегат сцены позволяет вам добавлять несколько windows в ваше приложение.

Вы узнали, как настроить делегат сцены для SwiftUI, раскадровки и программно. Мы также рассмотрели три компонента, которые обеспечивают работу сцен: делегат приложения, делегат сцены и манифест сцены приложения. Потрясающий!