В начале 2022 года может показаться, что использование UIKit на фоне SwiftUI не актуально или даже старомодно. Но так как еще очень много приложений которые созданы на основе фреймворка UIKit и у нас в России до сих пор на нем создается, то его актуальность еще на довольно солидном уровне. А еще более важным будет знание, как это работает. Сейчас идет постепенный переход от Storyboard к чистому коду в SwiftUI. Переход медленный и это дает нам возможность, еще пока, учится с помощью картинок и кода создавать приложения и одновременно учится создавать приложения с помощью кода. Давайте сразу перейдем к задаче: Создайте новый проект с названием Navigation, используя шаблон Single View App. Удалите из проекта Main.storyboard, который создался по умолчанию. Не забудьте изменить конфигурацию в Info.plist. В SceneDelegate.swift добавьте UITabBarController. Добавьте в него два UINavigationController. Первый будет показывать ленту пользователя, а второй — профиль. Измените Tab Bar Item у добавленных контроллеров, добавьте заголовок и картинку. Картинки можно добавить в Assets.xcassets или использовать SF Symbols. Создайте FeedViewController и ProfileViewController и добавьте их как root view controller у навигационных контроллеров. Добавьте PostViewController для показа выбранного поста. Поменяйте заголовок у контроллера и цвет главной view. Добавьте кнопку на FeedViewController и сделайте переход на экран поста. Контроллер должен показаться в стеке UINavigationController. Создайте структуру Post со свойством title: String. Создайте объект типа Post в FeedViewController и передайте его в PostViewController. В классе PostViewController выставьте title полученного поста в качестве заголовка контроллера. На PostViewController добавьте Bar Button Item в навигейшн бар. При нажатии на него должен открываться новый контроллер InfoViewController. Контроллер должен показаться модально. На InfoViewController создайте кнопку. При нажатии на неё должен показаться UIAlertController с заданным title, message и двумя UIAlertAction. При нажатии на UIAlertAction в консоль должно выводиться сообщение. В рамках данной статьи мы не будем рассматривать пункты 1 и 2. Не в смысле их примитивности, а потому-что подобными ответами пестрит интернет. Замечу только, что после удаления не забудьте вернуть в SceneDelegate (если вы еще используете Xcode до 13 версии, то AppDelegate), строку, которая удаляется автоматически с Main.storyboard. var window: UIWindow В данной статье мы рассмотрим пункты 3, 4, 5. Остальны в последующих статьях. Приступим! Для реализации пункта 2 существуют 2 способа:  Релизация UITabBarController  внутри SceneDelegate.swift Создание собственного UITabBarController.swift и в него инкапсулировать два UINavigationController Перейдем в SceneDelegate.swift и первым делом заменим ViewController на TabBarController window = UIWindow(frame: windowScene.coordinateSpace.bounds) window?.windowScene = windowScene window?.rootViewController = UITabBarController() window?.makeKeyAndVisible() Теперь можно удалить сам контроллер просмотра ViewController.swift. А сейчас мы пойдем от обратного. Наш TabBarController будет удерживать навигационные контроллеры и для того, чтобы TabBarController что-то отобразил, нам придется сначала создать навигационные контроллеры. Приступим. Создаем 2 ViewController (cmd⌘ + N -> Cocoa Touch Class), где Class: у нас будут FeedViewController и ProfileViewController, а Subclass of: UIViewController соответственно. С самого начала контроллеры прозрачные и для того, чтобы мы могли понять, что они у нас есть, мы зададим им фоновый цвет: override func viewDidLoad() {         super.viewDidLoad()         // Задаем фоновый цвет         view.backgroundColor = .lightGray }  Конечно для фона лучше использовать системные цвета (например: .systemBlue). Apple адаптировала системные цвета к темному и светлому режижам работы в отличии от простых цветов. В качестве эксперимента давай зададим нашим ViewController   разные цвета. Теперь давай создадим два навигационных контроллераr и добавимFeedViewController и ProfileViewController и как root view controller. В SceneDelegate.swift перед window = UIWindow(frame: windowScene.coordinateSpace.bounds  создаем навигационные контроллеры    let feedViewController = UINavigationController(rootViewController: FeedViewController())  let profileViewController = UINavigationController(rootViewController: profileViewController()) Теперь помещаем навигационные контроллеры в панель вкладок пользовательского интерфейса. Создаем панель вкладок:  let tabBarController = UITabBarController() Помещаем в нее навигационнные контроллеры: tabBarController.viewControllers = [feedViewController, profileViewController] Не забудь поменять UITabBarController()  на пользовательский  tabBarController  в window?.rootViewController = UITabBarController() Теперь когда мы запустим наш проект, мы увидим что экран отображает заданный цвет и если пощелкать внизу справа и слева, то даже будут переключаться экраны. Хотя наш TabBar  и не отображает ничего. Это говорит, что у нас все прекрасно работает. Давай теперь настроим наш TabBar, чтобы не играть в игру: Куда я нажимаю? Давай сделаем наш код красивым и не будем все собирать в кучу, а разделим каждый блок в методы. В первый метод соберем наш FeedViewController, во второй ProfileViewController, ну а в третий TabBarController. Реализация методов в SceneDelegate.swift станет выполнением пункда 6 нашего задания, мы добавим и иконки и заголовки.  Создаем фукцию контроллера поисковой навигации, который возвращает контроллер пользовательского интерфейса: func createFeedViewController() -> UINavigationController {  Инициализируем поисковый контроллер, который заменим созданный выше let feedViewController = FeedViewController() Добавляем заголовок, который отобразится вверху нашего экрана feedViewController.title = "Лента" А теперь настроим и саму кнопку, добавив на нее иконку и название. Создаем элемент панели вкладок пользовательского интерфейса UITabBarIt, где  title: это заголовок, а image: в нашем случае системная иконка (системные иконки можно найти в программе "Символы SF" или в самом Xcode Edit -> Emoji & Symbols) и последнее tag:это индекс положения, где 0 - положение слева, а 1 справа.      feedViewController.tabBarItem = UITabBarItem(title: "Лента", image: UIImage(systemName: "doc.richtext"), tag: 0) Возвращаем навигатор пользовательского интерфейса return UINavigationController(rootViewController: feedViewController) } Делаем тоже самое для навигационного контроллера  ProfileViewController      func createProfileViewController() -> UINavigationController { let profileViewController = ProfileViewController() profileViewController.title = "Профиль" profileViewController.tabBarItem = UITabBarItem(title: "Профиль", image: UIImage(systemName: "person.circle"), tag: 1) return UINavigationController(rootViewController: profileViewController) } Теперь удалим, за ненадобностью вверху:  let feedViewController = UINavigationController(rootViewController: FeedViewController())  let profileViewController = UINavigationController(rootViewController: profileViewController()) Теперь давай создадим метод для панели вкладок и передадим эту функцию корневому представлению func createTabBarController() -> UITabBarController { Удали сверху и вставь в метод строки кода let tabBarController = UITabBarController() Настроим внешний вид панели вкладок и установим основной цвет синий UITabBar.appearance().backgroundColor = .systemBlue Поменяем наши контроллеры на методы созданные чуть выше tabBarController.viewControllers = [createFeedViewController(), createProfileViewController()] Возвращаем панель вкладок return tabBarController } Не забудь поменять tabBarController()  созданный метод  createTabBarController()  в window?.rootViewController = tabBarController Теперь можещь запустить созданный проект и посмотреть на ту красоту, которую мы создали. Благодаря методам мы сделали красивый и хорошо пахнущий код, который не засоряет собою SceneDelegate.swift Давай перейдем ко второму методу. Кому-то может не понравится способ создания кода в SceneDelegate.swift  и это тоже хорошо и по-этому мы рассмотрим второй способ. Во-первых, мы создаем свой TabBarController final class TabBarController: UITabBarController { В него мы инкапсулируем FeedViewController, во второй ProfileViewControlle.  Мы можен инкапсулировать больше двух контроллеров, то есть сколько айтемов, столько и кейсов. Создаем перечисление TabBarItem с описанием наших контроллеров private enum TabBarItem: Int {         case feed         case profile         Добавим заголовки         var title: String {             switch self {             case .feed:                 return "Лента"             case .profile:                 return "Профиль"             }         }         Добавим иконки         var iconName: String {             switch self {             case .feed:                 return "house"             case .profile:                 return "person.crop.circle"             }         }     } Теперь загрузим это все в TabBarController override func viewDidLoad() {         super.viewDidLoad()         self.setupTabBar()     } В методе    мы создадим создадим контроллеры FeedViewController и ProfileViewControlle  для TabBarController. Не забудьте как и в первом способе создать сами swift файлы! private func setupTabBar() {         let dataSource: [TabBarItem] = [.feed, .profile]         self.viewControllers = dataSource.map {             switch $0 {             case .feed:                 let feedViewController = FeedViewController()                 return self.wrappedInNavigationController(with: feedViewController, title: $0.title)             case .profile:                 let profileViewController = ProfileViewController()                 return self.wrappedInNavigationController(with: profileViewController, title: $0.title)             }         }         self.viewControllers?.enumerated().forEach {             $1.tabBarItem.title = dataSource[$0].title             $1.tabBarItem.image = UIImage(systemName: dataSource[$0].iconName)             $1.tabBarItem.imageInsets = UIEdgeInsets(top: 5, left: .zero, bottom: -5, right: .zero)         }     } Ну и в самом конце методом wrappedInNavigationController(with: profileViewController, title: $0.title)  мы обернем переданный контроллер FeedViewController или ProfileViewControlleв NavigationController private func wrappedInNavigationController(with: UIViewController, title: Any?) -> UINavigationController {         return UINavigationController(rootViewController: with)     } Второй способ позволит нам оставить чистым SceneDelegate.swift   guard let windowScene = (scene as? UIWindowScene) else { return }         self.window = UIWindow(windowScene: windowScene)         self.window?.makeKeyAndVisible()         self.window?.rootViewController = TabBarController()          В следующей статье мы рассмотрим оставшиеся пункты, а так же программный способ создания интерфейса. Следующая статья рассматривающая пункты 6 и 7