SwiftUI је декларативни оквир (framework) компаније Apple за изградњу корисничких интерфејса на свим платформама екосистема. Уместо императивног описа корака, програмер изјављује како интерфејс треба да изгледа, а SwiftUI управља његовим приказивањем и ажурирањем. Према Apple Developer Documentation (2025), SwiftUI подржава iOS 15+, iPadOS 15+, macOS 12+, watchOS 8+ и tvOS 15+ и користи View Protocol као основни градивни блок за све компоненте интерфејса.
Главно
body — основа сваке UI компоненте SwiftUI, која враћа опис екрана кроз композицију приказа.SwiftUI је декларативни оквир, представљен од стране Apple 2019. године за замену UIKit-а у новим пројектима. Уместо ручног креирања инстанци UIView и додавања у хијерархију, програмер описује интерфејс кроз структуре које имплементирају протокол View. SwiftUI аутоматски израчунава разлику између тренутног и новог стања и прецртава само измењене делове, користећи сопствени мотор за рендеровање.
Оквир је написан у Swift-у коришћењем value semantics (структуре, а не класе), што чини UI компоненте лаганим и нитно безбедним. За разлику од UIKit-а, где UIViewController може тежити 200+ бајтова због Objective-C runtime-а, SwiftUI View је само структура величине неколико бајтова. Ово је посебно важно за watchOS са његовом ограниченом меморијом.
Исти опис View ради на iPhone, iPad, Mac, Apple Watch, Apple TV и Apple Vision Pro. SwiftUI прилагођава интерфејс платформи: на iOS — додирни гестови, на macOS — тастатурне пречице, на watchOS — скроловање Digital Crown. Ово скраћује време развоја за компаније које објављују апликације на више Apple платформи, али захтева додатно подешавање за специфичне елементе сваке платформе.
У SwiftUI-ју сваки екран је структура која имплементира протокол View са једним захтевом: computed својство body типа some View. Кључна реч some (opaque type) скрива конкретан тип приказа, омогућавајући SwiftUI-ју да оптимизује рендеровање. Унутар body-ја програмер комбинује готове компоненте — Text, Image, Button, List — помоћу ViewBuilder-а, који сакупља више приказа у један.
struct GreetingView: View {
let name: String
var var body: some View {
VStack {
Text("Zdravo, \(name)!")
.font(.title)
.foregroundColor(.blue)
Image(systemName: "hand.wave")
.imageScale(.large)
}
.padding()
}
}
У примеру VStack (вертикални стек) садржи Text и Image. Вредност name се прослеђује кроз иницијализатор структуре — тако ради DI (Dependency Injection) у SwiftUI-ју без спољних DI контејнера. Сваки модификатор враћа нови приказ са примењеном изменом, без мутирања оригинала. Ово је могуће захваљујући непроменљивости (immutability) value-типова.
ViewBuilder је result builder, анотиран са @resultBuilder, који сакупља до 10 приказа у један. Унутар body-ја се могу користити if/else, switch и ForEach без додатних омотача. ForEach ради са Identifiable елементима — сваком приказу се додељује јединствени id за коректну анимацију при уметању/брисању.
У SwiftUI-ју стање одређује који садржај се приказује на екрану. Када се стање промени, SwiftUI поново креира body зависног приказа и упоређује резултат са претходним, примењујући diff алгоритам. За чување стања користе се property wrappers — сваки решава свој задатак: локално стање, веза са подређеним приказом или спољни модел података.
struct CounterView: View {
@State private var count = 0
var var body: some View {
VStack {
Text("Brojač: \(count)")
Button("Povećaj") {
count += 1
}
}
}
}
class UserViewModel: ObservableObject {
@Published var name = ""
@Published var age = 0
}
@State чува локалну једноставну вредност (Int, String, Bool) унутар структуре View. SwiftUI измешта меморију из структуре у засебно складиште — зато се својство са @State може мењати (мутирати), чак и ако је View value-тип. @ObservableObject — за класе са @Published својствима, чије промене аутоматски обавештавају SwiftUI о потреби за прецртавањем.
@Binding ствара двосмерну везу са извором података који се налази у родитељском приказу. Родитељ прослеђује $variable (projected value), дете чита и уписује вредност кроз binding. Ово омогућава издвајање уноса текста или прекидача у засебну компоненту, чувајући стање у родитељу. Без @Binding-а свака промена би захтевала callback затварање за прослеђивање нове вредности навише.
Пре iOS 16, навигација у SwiftUI-ју се заснивала на NavigationView — застарелом API-ју са сложеним понашањем на iPad-у (split view, double column). Од iOS 16, Apple препоручује NavigationStack — поједностављену алтернативу са типно-безбедним рутама. Програмер дефинише enum могућих рута, а NavigationStack аутоматски управља стеком екрана са подршком за дубоке линкове и повратак на корен.
enum Route: Hashable {
case detail(id: Int)
case settings
}
struct ContentView: View {
var var body: some View {
NavigationStack {
List {
NavigationLink("Ekran detalja",
value: Route.detail(id: 42))
NavigationLink("Podešavanja",
value: Route.settings)
}
.navigationDestination(for: Route.self) { route in
switch route {
case .detail(let id): DetailView(id: id)
case .settings: SettingsView()
}
}
}
}
}
Руте типа Route: Hashable омогућавају коришћење било ког типа података за прослеђивање параметара. navigationDestination(for:destination:) повезује тип руте са циљним приказом. Предност у односу на UIKit навигацију — прецртавање није потребно при додавању нове руте: довољно је додати case у enum и handler у switch. Дубоки линкови се обрађују кроз processDeepLink на NavigationStack-у.
За програмски прелаз (након пријаве, тајмера или одговора сервера) користи се @State са NavigationLink иницијализатором: NavigationLink(isActive: $isActive). По постављању isActive = true прелаз се извршава без додира корисника. Алтернатива — binding низа $path у NavigationStack-у: $path.append(Route.detail(id: 1)).
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-ја и UIKit-а једна је од првих дилема iOS програмера. Оба оквира подржава Apple, али решавају задатак изградње интерфејса на суштински различите начине: SwiftUI декларативно, UIKit императивно. Разлика се манифестује у управљању стањем, навигацији, перформансама и компатибилности.
| Аспект | SwiftUI | UIKit |
|---|---|---|
| Приступ | Декларативни: шта приказати | Императивни: како изградити |
| Стање | 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 хијерархије.
Често постављана питања
Да, кроз UIHostingController (SwiftUI у UIKit) и UIViewRepresentable (UIKit у SwiftUI). Ово је хибридни приступ, популаран при миграцији.
iOS 17 — пуна функционалност: NavigationStack, Observation framework, Swift Charts. iOS 15 — минимални праг за продукцију.
Најчешћи узрок је промена @Published својства на позадинској нити. ObservableObject мора да шаље промене на main actor: @MainActor class ViewModel.
Користите .debounce кроз Combine: Button.publisher(for: .tap) .debounce(for: .seconds(0.3), scheduler: RunLoop.main).
Да, кроз Gesture модификаторе: DragGesture, LongPressGesture, MagnificationGesture, RotationGesture. Комбинујте их кроз .simultaneousGesture() и .sequenced().
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође