Основни точки
View Protocol е централният протокол на SwiftUI. Изисква само едно свойство: var body: some View. body е изчисляемо свойство, което връща описанието на UI. SwiftUI извиква body при всяка промяна на състоянието и рендерира резултата на GPU.
@ViewBuilder е Result Builder за Views. Позволява писане на множество Views вътре в closure без return и без TupleView. Поддържа if/else, switch, ForEach. Всички контейнери (VStack, HStack, ZStack, Group) използват @ViewBuilder. Алтернатива е Group { … } за групиране без оформление. some View е Opaque Type. Компилаторът знае конкретния тип View (Text, Button, VStack и т.н.), но го връща външно като some View. Това позволява промяна на типа на body без промяна на подписа. ViewModifier — модификатор на View: .font(), .padding(), .background(). Персонализиран модификатор чрез ViewModifier protocol и .modifier().
// Пример за View с @ViewBuilder и NavigationStack
struct ContentView: View {
@State private var items = ["Item 1", "Item 2"]
var body: some View {
NavigationStack {
List(items, id: .self) { item in
NavigationLink(item) {
DetailView(item: item)
}
}
.navigationTitle("Items")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add") {
items.append("New Item")
}
}
}
}
}
}
// DetailView с @StateObject
struct DetailView: View {
let item: String
@StateObject private var viewModel = DetailViewModel()
var body: some View {
Text(item)
.task {
await viewModel.loadDetails(for: item)
}
}
}NavigationStack (iOS 16+) — навигация, управлявана от данни. Приема път (масив от hashable стойности) и показва дестинацията чрез navigationDestination. Заменя NavigationLink с дестинационни изгледи. NavigationLink — бутон за навигация в стека. List — вертикален списък с раздели, плъзгания, изтриване и влачене и пускане. Form — специализиран List за настройки: раздели, избиратели, превключватели, текстови полета. Section — групиране в List/Form с заглавка и долен колонтитул. ViewModifier — персонализирани модификатори за повторна употреба на стилове. .modifier(CustomModifier()) — прилагане.
List в SwiftUI е еквивалентът на UITableView. Поддържа .onDelete, .onMove, .refreshable. SwipeActions — .swipeActions { Button("Изтрий", role: .destructive) { } }. Form — оптимизиран за настройки: DatePicker, Toggle, Stepper, Picker. Section с header/footer — за групиране. OutlineGroup — йерархични списъци (еквивалент на UITableView с раздели). DisclosureGroup — свиваем раздел със съдържание. IT Sectr препоръчва List за данни и Form за настройки.
PreviewProvider — протокол за прегледи в Xcode Canvas. Canvas — интерактивен преглед на SwiftUI (изисква @main и Swift 5.9+). @ScaledMetric — адаптивен размер, който се мащабира с Dynamic Type.
Property Wrappers са основата на управлението на състоянието в SwiftUI. @State — локално състояние (тип стойност). @Binding — връзка със състоянието на родителя. @StateObject — създава ObservableObject. SwiftUI управлява жизнения цикъл на обекта. @ObservedObject — наблюдава външен ObservableObject. @EnvironmentObject — обект от средата (инжектиране на зависимости чрез .environmentObject()). @Environment — системни стойности (.colorScheme, .locale). @AppStorage — UserDefaults. @FetchRequest — Core Data заявка. @FocusState — фокус на въвеждане.
| Обвивка | Предназначение | Собственост |
|---|---|---|
| @State | Локално състояние (тип стойност) | View притежава |
| @Binding | Връзка със състоянието на родителя | Родителят притежава |
| @StateObject | Създава ObservableObject | View притежава |
| @ObservedObject | Наблюдава външен обект | Външен собственик |
| @EnvironmentObject | Обект от средата | Предшественик притежава |
| @Environment | Системна стойност | Системата |
| @AppStorage | UserDefaults | UserDefaults |
| @FocusState | Фокус на въвеждане | View притежава |
@StateObject срещу @ObservedObject: @StateObject създава обект, @ObservedObject го наблюдава. Използвайте @StateObject за първото създаване на модел в йерархията, @ObservedObject за предаване на дъщерни изгледи. @FocusState — управление на фокуса: .focused($field, equals: .email). Поддържа enum за множество полета.
@Environment — системни стойности: colorScheme, locale, sizeCategory, layoutDirection, managedObjectContext. Персонализирани стойности на средата — персонализирана стойност чрез EnvironmentKey. Използва се за инжектиране на зависимости: предаване на услуги без изрични параметри. Модификатор .environment() — задава стойност в йерархията. @EnvironmentObject — ObservableObject от .environmentObject(). Различава се от @Environment по това, че предава референтен тип. IT Sectr препоръчва @Environment за системни стойности и @EnvironmentObject за услуги.
.task{} — асинхронна операция при появата на изгледа. Автоматично отменяне при изчезване. Заменя .onAppear за async/await. .onAppear{} — синхронна операция при поява. .onDisappear{} — операция при изчезване. .onChange(of:) — реакция на промени в стойността. .onReceive(Publisher) — реакция на Combine publisher. Жизнен цикъл на View в SwiftUI: init → onAppear → body (рендериране) → onDisappear. При промяна на състоянието: body → diff → повторно рендериране. IT Sectr препоръчва .task за асинхронно зареждане и .onAppear за аналитика.
.animation() — модификатор на анимация. .transition() — анимация на появяване/изчезване. withAnimation — изрична анимация на промяна на състоянието. matchedGeometryEffect — анимация между различни изгледи (hero animation). PhaseAnimator (iOS 17+) — многофазова анимация на базата на enum. KeyframeAnimator (iOS 17+) — покадрова анимация с ключови кадри. SwiftUI анимациите се изпълняват на GPU чрез Core Animation. IT Sectr препоръчва .spring() за естествени анимации и .interpolatingSpring за физически ефекти.
ObservableObject — протокол за обекти с @Published свойства. SwiftUI се абонира за objectWillChange publisher. @Published — публикува промени на свойства. @StateObject — създава ObservableObject, управлява жизнения цикъл. @ObservedObject — наблюдава външен. Combine — рамка за реактивно програмиране. @EnvironmentObject — DI чрез среда. .environmentObject() задава, @EnvironmentObject чете. MVVM — стандартна архитектура: View (SwiftUI) — ViewModel (ObservableObject) — Model. IT Sectr препоръчва MVVM + @StateObject за основните ViewModel-и.
class UserViewModel: ObservableObject {
@Published var users: [User] = []
@Published var isLoading = false
func loadUsers() async {
isLoading = true
defer { isLoading = false }
do {
users = try await api.fetchUsers()
} catch {
print("Грешка: \(error)")
}
}
}
struct UsersView: View {
@StateObject private var viewModel = UserViewModel()
var body: some View {
List(viewModel.users, id: \.id) { user in
Text(user.name)
}
.task { await viewModel.loadUsers() }
.overlay {
if viewModel.isLoading { ProgressView() }
}
}
}Достъпност в SwiftUI: .accessibilityLabel(), .accessibilityHint(), .accessibilityValue(), .accessibilityAddTraits(). VoiceOver чете етикетите за достъпност. Dynamic Type — @ScaledMetric, @DynamicProperty. Локализация: String(localized:) (SwiftUI + String Catalog). LocalizedStringKey — автоматичен превод. Правила за множествено число — чрез String Catalog (one, few, many, other). Отдясно наляво (арабски, иврит) — автоматично поддържано. .environment(.layoutDirection, .rightToLeft). IT Sectr препоръчва етикети за достъпност за всички интерактивни елементи.
struct AccessibleButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
Label("Settings", systemImage: "gear")
}
.accessibilityLabel("Open Settings")
.accessibilityHint("Double tap to navigate to settings screen")
.accessibilityAddTraits(.isButton)
}
}
// Поддръжка на Dynamic Type
struct ScalableText: View {
@ScaledMetric private var fontSize: CGFloat = 17
var body: some View {
Text("Hello, World!")
.font(.system(size: fontSize))
}
}Swift Charts (iOS 16+) — рамка за изграждане на диаграми. Chart { } — основен контейнер. BarMark, LineMark, PointMark, AreaMark, RuleMark — марки. ForEach за данни. ChartAxis — персонализиране на оси. .chartXAxis, .chartYAxis. ChartLegend — легенда. Интерполация — catmullRom, linear, step. Анимация — .animation() за Chart. IT Sectr препоръчва Swift Charts за вградени диаграми и Charts (DGCharts) за сложни.
import Charts
struct MonthlySales: Identifiable {
let id = UUID()
let month: String
let sales: Double
}
struct SalesChart: View {
let data: [MonthlySales]
var body: some View {
Chart(data) { item in
BarMark(
x: .value("Month", item.month),
y: .value("Sales", item.sales)
)
.foregroundStyle(.blue.gradient)
}
.chartXAxisLabel("Month")
.chartYAxisLabel("Sales")
.frame(height: 200)
.padding()
}
}Swift Package Manager (SPM) — мениджърът на зависимости на Apple. Интегриран в Xcode. Поддържа: двоични пакети, ресурси, тестове, swift-6 строга конкурентност. Публикуване на пакети чрез GitHub с маркер semver. SPM е де факто стандартът за Swift зависимости, измествайки CocoaPods и Carthage. IT Sectr препоръчва SPM за всички нови проекти.
Swift Concurrency (async/await, TaskGroup, AsyncSequence) — async/await са вградени в Swift 5.5+. Task — единица за асинхронност. TaskGroup — паралелни задачи. AsyncSequence — асинхронна последователност (AsyncStream, AsyncAlgorithms). Task Local Values — контекстни данни за Task. Swift Concurrency напълно замества Combine за асинхронни операции.
Често задавани въпроси
View Protocol е основният протокол. Изисква var body: some View. body е описанието на UI, рендерирано на GPU.
@ViewBuilder е Result Builder за множество Views. Позволява if/else, switch, ForEach в контейнери.
@StateObject създава обект. @ObservedObject наблюдава съществуващ. @StateObject за първо създаване в йерархията.
NavigationStack — навигация, управлявана от данни. path-based, deep linking. Заменя NavigationView.
@FocusState — управление на фокуса на въвеждане. Модификатор .focused(). Поддържа enum за множество полета.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.