SwiftUI: що це, ключові поняття та View Protocol

Автор: IT Sectr Опубліковано: 2026-04-30 Час читання: 8 хв

SwiftUI — це декларативний фреймворк від Apple для побудови користувацьких інтерфейсів на всіх платформах екосистеми. Замість імперативного опису кроків розробник оголошує, як має виглядати інтерфейс, а SwiftUI керує його відмальовуванням та оновленням. За даними Apple Developer Documentation (2025), SwiftUI підтримує iOS 15+, iPadOS 15+, macOS 12+, watchOS 8+ та tvOS 15+ і використовує View Protocol як базовий будівельний блок для всіх компонентів інтерфейсу.

Головне

  • SwiftUI — декларативний фреймворк Apple, в якому розробник описує інтерфейс, а оновлення виконуються автоматично.
  • View Protocol з property body — основа будь-якого UI-компонента SwiftUI, що повертає опис екрана через композицію в'юх.
  • Property Wrappers — @State, @Binding, @ObservedObject, @StateObject — керують станом і запускають перемальовування при зміні даних.
  • NavigationStack (iOS 16+) — сучасний API навігації з типобезпечними маршрутами та декларативними переходами.
  • Modifier — ланцюжок викликів для налаштування зовнішнього вигляду та поведінки в'юх без успадкування класів.

Що таке SwiftUI?

SwiftUI — це декларативний фреймворк, представлений Apple у 2019 році для заміни UIKit у нових проєктах. Замість того щоб вручну створювати екземпляри UIView і додавати їх до ієрархії, розробник описує інтерфейс через структури, що відповідають протоколу View. SwiftUI автоматично обчислює різницю між поточним і новим станом і перемальовує лише змінені частини, використовуючи власний рушій рендерингу.

Фреймворк написаний на Swift з використанням value semantics (структури, а не класи), що робить UI-компоненти легковаговими та потокобезпечними. На відміну від UIKit, де UIViewController може важити 200+ байтів через Objective-C runtime, SwiftUI View — це просто структура розміром у кілька байтів. Це особливо важливо для watchOS з її обмеженою пам'яттю.

Кроссплатформеність SwiftUI

Один і той самий опис View працює на iPhone, iPad, Mac, Apple Watch, Apple TV та Apple Vision Pro. SwiftUI адаптує інтерфейс під платформу: на iOS — сенсорні жести, на macOS — клавіатурні комбінації, на watchOS — прокрутку Digital Crown. Це скорочує час розробки для компаній, які випускають застосунки на кілька платформ Apple, але потребує додаткового налаштування для специфічних елементів кожної платформи.

View Protocol та тіло представлення

У SwiftUI кожен екран — це структура, що реалізує протокол View з єдиною вимогою: обчислювана властивість body типу some View. Ключове слово some (opaque type) приховує конкретний тип в'юхи, дозволяючи SwiftUI оптимізувати рендеринг. Усередині body розробник комбінує готові компоненти — Text, Image, Button, List — за допомогою ViewBuilder, який збирає кілька в'юх в одну.

swift
struct GreetingView: View {
    let name: String

    var var body: some View {
        VStack {
            Text("Привіт, \(name)!")
                .font(.title)
                .foregroundColor(.blue)
            Image(systemName: "hand.wave")
                .imageScale(.large)
        }
        .padding()
    }
}

У прикладі VStack (вертикальний стек) містить Text та Image. Значення name передається через ініціалізатор структури — так працює DI (Dependency Injection) у SwiftUI без зовнішніх DI-контейнерів. Кожен модифікатор повертає нову в'юху з застосованою зміною, не мутуючи оригінал. Це можливо завдяки незмінності (immutability) value-типів.

ViewBuilder та умовні конструкції

ViewBuilder — це result builder, анотований @resultBuilder, який збирає до 10 в'юх в одну. Усередині body можна використовувати if/else, switch та ForEach без додаткових обгорток. ForEach працює з елементами Identifiable — кожній в'юсі присвоюється унікальний id для коректної анімації під час вставки/видалення.

Керування станом: @State, @Binding, @ObservedObject

У SwiftUI стан визначає, який контент відображається на екрані. Коли стан змінюється, SwiftUI перестворює body залежної в'юхи та порівнює результат із попереднім, застосовуючи diff-алгоритм. Для зберігання стану використовуються property wrappers — кожен із них вирішує своє завдання: локальний стан, зв'язок із дочірньою в'юхою або зовнішня модель даних.

swift
struct CounterView: View {
    @State private var count = 0

    var var body: some View {
        VStack {
            Text("Лічильник: \(count)")
            Button("Збільшити") {
                count += 1
            }
        }
    }
}

class UserViewModel: ObservableObject {
    @Published var name = ""
    @Published var age = 0
}

@State зберігає локальне просте значення (Int, String, Bool) усередині структури View. SwiftUI виносить пам'ять зі структури в окреме сховище — тому властивість з @State можна змінювати (mutate), навіть якщо View — value-тип. @ObservableObject — для класів із властивостями @Published, зміни яких автоматично повідомляють SwiftUI про необхідність перемалювання.

@Binding та зв'язок батько-дитина

@Binding створює двосторонній зв'язок із джерелом даних, розташованим у батьківській в'юсі. Батько передає $variable (projected value), дитина читає та записує значення через binding. Це дозволяє винести введення тексту або перемикач в окремий компонент, зберігши стан у батькові. Без @Binding кожна зміна вимагала б callback-замикання для передачі нового значення нагору.

До iOS 16 навігація в SwiftUI будувалася на NavigationView — застарілому API зі складною поведінкою на iPad (split view, double column). Починаючи з iOS 16, Apple рекомендує NavigationStack — спрощену альтернативу з типобезпечними маршрутами. Розробник визначає enum можливих маршрутів, і NavigationStack автоматично керує стеком екранів із підтримкою глибоких посилань та повернення до кореня.

swift
enum Route: Hashable {
    case detail(id: Int)
    case settings
}

struct ContentView: View {
    var var body: some View {
        NavigationStack {
            List {
                NavigationLink("Детальний екран",
                               value: Route.detail(id: 42))
                NavigationLink("Налаштування",
                               value: Route.settings)
            }
            .navigationDestination(for: Route.self) { route in
                switch route {
                case .detail(let id): DetailView(id: id)
                case .settings: SettingsView()
                }
            }
        }
    }
}

Маршрути, що відповідають Hashable, дозволяють використовувати будь-який тип даних для передачі параметрів. navigationDestination(for:destination:) пов'язує тип маршруту з цільовою в'юхою. Перевага перед UIKit-навігацією — перемальовування не потрібне при додаванні нового маршруту: достатньо додати case в enum та обробник у switch. Глибокі посилання обробляються через processDeepLink на NavigationStack.

Програмна навігація

Для програмного переходу (після логіну, таймера або відповіді сервера) використовується @State з ініціалізатором NavigationLink: NavigationLink(isActive: $isActive). При встановленні isActive = true перехід виконується без дотику користувача. Альтернатива — зв'язування масиву $path у NavigationStack: $path.append(Route.detail(id: 1)).

View Modifier — налаштування зовнішнього вигляду

Modifier — це метод, що повертає модифіковану копію в'юхи. На відміну від UIKit, де налаштування властивостей виконується через мутацію існуючої в'юхи, SwiftUI створює нове значення із застосованою зміною. Ланцюжок модифікаторів (chaining) збирає кінцевий інтерфейс із послідовних перетворень: шрифт → відступ → колір → тінь → жест.

Apple надає понад 200 вбудованих модифікаторів. Найпоширеніші: .font(), .foregroundColor(), .padding(), .background(), .cornerRadius(), .shadow(), .opacity(), .offset(). Порядок модифікаторів важливий: .padding() до .background() зафарбовує область із відступом, після — лише внутрішню область. Кастомні модифікатори створюються через протокол ViewModifier.

Умовні модифікатори та анімація

Модифікатори можна застосовувати умовно через тернарний оператор: .foregroundColor(isError ? .red : .primary). Для анімації використовується .animation(.easeInOut, value: state) — модифікатор анімації прив'язується до конкретної властивості стану. При зміні цієї властивості SwiftUI анімує перехід між старим і новим значенням. Анімація працює з opacity, offset, scale, rotation, розміром і кольором — для кожної властивості визначено відповідний AnimatableParameter.

Для кастомних анімацій доступні .transition (поява/зникнення) та .matchedGeometryEffect (плавний перехід елемента між двома контейнерами). Останній використовується для hero-анімації в списках: іконка в комірці списку плавно перетворюється на велике зображення на детальному екрані.

SwiftUI vs UIKit: порівняння підходів

Вибір між SwiftUI та UIKit — одна з перших дилем iOS-розробника. Обидва фреймворки підтримуються Apple, але вирішують завдання побудови інтерфейсу принципово різними способами: SwiftUI декларативно, UIKit імперативно. Різниця проявляється в керуванні станом, навігації, продуктивності та сумісності.

АспектSwiftUIUIKit
ПідхідДекларативний: що показатиІмперативний: як побудувати
СтанProperty Wrappers, автоматичне перемальовуванняВручну: reloadData, setNeedsLayout
Код UIКомпактний, ланцюжки модифікаторівОб'ємний, NSCoder/Storyboard/обмеження
ПродуктивністьВисока на iOS 17+, diff-алгоритмПікова на iOS 12–16, прямий контроль
Мінімальна версіяiOS 15+ (повна підтримка)iOS 2+ (всі версії)

Для нових проєктів із мінімальною версією iOS 17 Apple рекомендує SwiftUI як основний фреймворк. UIKit залишається необхідним для інтерфейсів, що потребують тонкого контролю над рендерингом (кастомні UICollectionViewLayout, складні CAAnimation-сцени) або підтримки iOS 12–14. Багато проєктів використовують гібридний підхід: SwiftUI через UIHostingController вбудовується в UIKit-застосунок, а UIViewRepresentable дозволяє використовувати UIKit-компоненти всередині SwiftUI-ієрархії.

Часті запитання

Чи можна використовувати SwiftUI та UIKit в одному проєкті?

Так, через UIHostingController (SwiftUI в UIKit) та UIViewRepresentable (UIKit в SwiftUI). Це гібридний підхід, популярний при міграції.

З якої версії iOS починати проєкт на SwiftUI?

З iOS 17 — повний функціонал: NavigationStack, Observation framework, Swift Charts. iOS 15 — мінімальний поріг для production.

Чому SwiftUI іноді не оновлює інтерфейс?

Найчастіша причина — зміна властивості @Published на фоновому потоці. ObservableObject має надсилати зміни на main actor: @MainActor class ViewModel.

Як у SwiftUI обробити натискання кнопки з затримкою?

Використовуйте .debounce через Combine: Button.publisher(for: .tap) .debounce(for: .seconds(0.3), scheduler: RunLoop.main).

Чи підтримує SwiftUI кастомні жести?

Так, через модифікатори Gesture: DragGesture, LongPressGesture, MagnificationGesture, RotationGesture. Комбінуйте через .simultaneousGesture() та .sequenced().

Підсумки

  • SwiftUI — декларативний фреймворк Apple, де інтерфейс описується у вигляді композиції структур View із property wrappers для керування станом.
  • View Protocol з обчислюваною властивістю body — єдина точка входу для будь-якої в'юхи. ViewBuilder збирає до 10 в'юх в одну без зайвих контейнерів.
  • @State, @Binding та @ObservedObject покривають усі сценарії керування даними: локальний стан, зв'язок батько-дитина та зовнішні моделі.
  • NavigationStack із типобезпечними enum-маршрутами замінив NavigationView, додавши підтримку глибоких посилань і програмної навігації.
  • Modifier — ключовий патерн SwiftUI, що дозволяє налаштовувати зовнішній вигляд в'юх через ланцюжок викликів без успадкування.
  • SwiftUI та UIKit співіснують через UIHostingController та UIViewRepresentable, дозволяючи мігрувати проєкт поступово.
  • Для iOS 17+ Apple рекомендує SwiftUI як основний фреймворк; UIKit залишається для складних кастомних інтерфейсів і підтримки старих версій.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також