View Protocol — SwiftUI-nin fundamental protokoludur və interfeysin hər bir vizual komponenti ona uyğun olmalıdır. Apple Developer Documentation, 2024-ə görə, View vahid kontrakt müəyyən edir: bu protokolu reallaşdıran struktur və ya sinif hesablanan body xassəsini təmin etməlidir. SwiftUI bu protokol vasitəsilə sadə mətn etiketlərindən tutmuş mürəkkəb naviqasiya strukturlarına qədər bütün ekran iyerarxiyasını qurur.
Əsas məqamlar
View Protocol — SwiftUI-nin mərkəzi protokoludur, hər bir vizual elementin öz məzmununu necə təsvir etdiyini müəyyən edir. UIKit-dən fərqli olaraq, burada hər element siniflər vasitəsilə UIView-dən miras alır, SwiftUI isə protokol yönümlü yanaşmadan istifadə edir: View protokoluna uyğun gələn istənilən tip ekranda göstərilə bilər.
View protokolu yalnız bir hesablanan body xassəsinin reallaşdırılmasını tələb edir. Lakin bu sadəliyin arxasında güclü kompozisiya sistemi dayanır: body primitivləri (Text, Image, Button), konteynerləri (VStack, HStack, ZStack) və fərdi mürəkkəb komponentləri əhatə edən View-ə uyğun istənilən tipi qaytara bilər.
WWDC 2023-ə görə, SwiftUI tətbiqlərində bütün ekranların 95%-dən çoxu View protokolunu reallaşdıran strukturların kompozisiyası vasitəsilə qurulur. Bu, View Protocol-u SwiftUI arxitekturasının təməlinə çevirir.
SwiftUI View-in value type (struktur, struct) olmasını tələb edir, sinif yox. Bu əsas arxitektura qərarıdır: value types proqnozlaşdırıla bilən ömür dövrünə malikdir, ortaq dəyişən vəziyyətə sahib deyil və SwiftUI-yə iyerarxiyanın hansı hissələrinin dəyişdiyini və yenidən çəkilməsini effektiv müəyyən etməyə imkan verir.
View-i sinif etməyə çalışsanız, kompilyator səhv verəcək: View protokolu value semantics tələb edən DynamicViewProperty protokolundan miras alır. Siniflər View-ə uyğun ola bilər, lakin bu idiomatik yanaşmanı pozur və avtomatik yeniləmə üstünlüklərini itirir.
body — View protokolunun yeganə məcburi tələbidir. Bu, ekranda göstərilən məzmunu qaytaran hesablanan xassədir. Qaytarılan dəyərin tipi — some View, yəni "kompilyator tərəfindən müəyyən ediləcək View-ə uyğun müəyyən tip".
struct GreetingView: View {
var name: String
var body: some View {
VStack {
Text("Salam, \(name)!")
.font(.title)
.foregroundColor(.blue)
Button("Başla") {
print("Düymə basıldı")
}
}
}
}
body necə işləyir: SwiftUI tətbiqin vəziyyəti dəyişdikdə və yenidən çəkmə tələb olunduqda body-ni hər dəfə çağırır. Framework yeni View ağacını köhnəsi ilə müqayisə edir və yalnız zəruri dəyişiklikləri tətbiq edir (diffing). Bu tamamilə deklarativ yanaşmadır — siz nəyin göstərilməli olduğunu təsvir edirsiniz, SwiftUI isə bunun necə reallaşdırılmasına qayğı göstərir.
Vacib detal: body-nin yan təsirləri olmamalıdır. O, tətbiqin ömrü boyu dəfələrlə çağırılır və əgər body daxilində xarici vəziyyət dəyişirsə — bu proqnozlaşdırıla bilməyən davranışa gətirib çıxarır. Yan təsirlər üçün task, onChange və ya DispatchQueue istifadə edin.
SwiftUI məhdudiyyət qoyur: body yalnız bir kök element qaytara bilər. Bir səviyyədə bir neçə element göstərmək lazımdırsa, onları konteynerə — VStack, HStack, ZStack və ya Group-a yerləşdirin. @ViewBuilder-in meydana çıxması ilə bu məhdudiyyət daha az nəzərə çarpır, lakin konseptual olaraq body həmişə bir View qaytarır.
some View — Swift 5.1-də xüsusi olaraq SwiftUI üçün tətbiq edilən qeyri-şəffaf tip (opaque type) sintaksisidir. Bu o deməkdir ki, funksiya və ya xassə View protokoluna uyğun konkret tip qaytarır, lakin çağıran kod hansı dəqiq tipin qaytarıldığını bilmir və bilməməlidir.
Swift kompilyatoru hər body reallaşdırması üçün kompilyasiya mərhələsində konkret tipi müəyyən edir, lakin onu xarici dünyadan gizlədir. Bu, SwiftUI-yə bütün komponentlərin dəqiq tiplərini bilərək View iyerarxiyasını optimallaşdırmağa imkan verir, lakin proqramçıya imzanı dəyişmədən reallaşdırmanı dəyişmək çevikliyi verir.
struct ContentView: View {
var body: some View {
Text("Salam, Dünya!") // Kompilyator bunun Text olduğunu bilir
}
}
Niyə some View, sadəcə View yox? Əgər body sadəcə View (protokol kimi) qaytarsaydı, SwiftUI kompilyasiya zamanı konkret tipi müəyyən edə bilməzdi. Bu, ekzistensial konteynerə (existential container) yerləşdirmə üçün əlavə yükə səbəb olur. some View optimallaşdırma üçün kompilyatora kifayət qədər məlumat verir, protokolun çevikliyini qoruyur.
Əsas məhdudiyyət — body eyni tipi qaytarmalıdır. Xüsusi sarğılar (AnyView, Group və ya @ViewBuilder) olmadan şərtin bir qolunda Text, digərində Image qaytarmaq olmaz. Kompilyator bunu kompilyasiya mərhələsində yoxlayır: bütün mümkün qaytarma yolları eyni tipə malik olmalıdır.
Bu məhdudiyyəti keçmək üçün @ViewBuilder (vahid TupleView tipi yaradır), Group (eyni zamanda vahid tip qaytarır) və ya AnyView (tipi silir, lakin yük əlavə edir) istifadə olunur. AnyView yalnız digər variantlar mümkün olmadıqda istifadə edilməlidir, çünki SwiftUI optimallaşdırmalarını söndürür.
@ViewBuilder — bir neçə View-i iç-içə konteynerlər olmadan bir kompozisiyada yığmağa imkan verən result builder annotasiyasıdır. @ViewBuilder avtomatik olaraq çoxsaylı ifadələri kortejə (TupleView) yerləşdirir və ya düzgün qaytarma tipi ilə şərti məntiq (If / else / switch) tətbiq edir.
struct DashboardView: View {
var isLoggedIn: Bool
@ViewBuilder
var body: some View {
if isLoggedIn {
Text("Xoş gəldiniz!")
.font(.largeTitle)
ProfileCard()
} else {
LoginButton()
.padding()
}
}
}
@ViewBuilder necə işləyir: kompilyator @ViewBuilder daxilindəki hər bir kod blokunu buildBlock, buildEither, buildOptional və s. statik metod çağırışlarına çevirir. Blokda bir neçə ifadə varsa — onlar TupleView-ə yerləşdirilir. Blokda şərti məntiq varsa — kompilyator qol tipini gizlədən ConditionalContent yaradır.
@ViewBuilder məhdudiyyət qoyur: bir blokda 10 elementə qədər (TupleView məhdudiyyəti). Ondan çox element yığmaq lazımdırsa, Group, ForEach istifadə edin və ya alt komponentlərə bölün. Bu məhdudiyyət Swift-in hər arilik üçün 1-dən 10-a qədər buildBlock üçün ayrıca overload yaratması səbəbindən mövcuddur.
Kompozisiya — SwiftUI-nin əsas prinsipi: mürəkkəb interfeyslər kiçik, təkrar istifadə olunan View komponentlərindən qurulur. Hər bir komponent View protokolunu reallaşdırır və ekranın öz hissəsinə cavabdehdir. Modifikatorlar (font, padding, foregroundColor) View-ə tətbiq edilir və dəyişdirilmiş parametrlərlə yeni View qaytarır.
SwiftUI-də modifikatorlar mutasiya deyil, orijinal View ətrafında yeni sarğı yaradır. Hər bir modifikator yeni tip (ModifiedContent) qaytarır ki, bu da SwiftUI-yə modifikatorlar ağacı qurmağa və yalnız dəyişmiş hissələri effektiv yenidən çəkməyə imkan verir. Modifikatorların tətbiq ardıcıllığı vacibdir: müxtəlif ardıcıllıqlar fərqli vizual nəticə verir.
Text("Salam, SwiftUI!")
.font(.title) // ModifiedContent
.padding() // ModifiedContent<..., PaddingModifier>
.background(.yellow) // ModifiedContent<..., BackgroundModifier>
.cornerRadius(8) // ModifiedContent<..., CornerRadiusModifier>
Performans optimallaşdırması: SwiftUI konkret View dəyərlərini deyil, onların eyniliyini identity mexanizmi (id, ForEach, strukturların stabil eyniliyi) vasitəsilə müqayisə edir. View strukturu dəyişməyibsə — body çağırılmır. Buna Equatable müqayisəsi və iyerarxiyada yuxarıya məlumat ötürmək üçün PreferenceKey mexanizmi vasitəsilə nail olunur.
Effektiv kompozisiya üçün mürəkkəb ekranları müstəqil alt komponentlərə bölmək tövsiyə olunur, hər biri öz minimal vəziyyəti ilə. Bu, SwiftUI-yə bütün ekranı deyil, yalnız dəyişmiş iyerarxiya hissələrini yenidən çəkməyə imkan verir.
Tez-tez verilən suallar
View Protocol — SwiftUI-nin əsas protokoludur, hər bir göstərilən komponent ona uyğun olmalıdır. Məzmun qaytaran yeganə hesablanan body xassəsini tələb edir. SwiftUI-nin bütün standart elementləri — Text, Button, Image, VStack — bu protokolu reallaşdırır.
SwiftUI interfeysin proqnozlaşdırıla bilən yenilənməsi üçün value semantics istifadə edir. Strukturların ortaq dəyişən vəziyyəti yoxdur, bu da SwiftUI-yə köhnə və yeni View iyerarxiyasını effektiv müqayisə etməyə və yalnız dəyişmiş elementləri yenidən çəkməyə imkan verir. Siniflər bu optimallaşdırmanı pozur.
body some View qaytarır — konkret reallaşdırmanı gizlədən qeyri-şəffaf tip. Faktiki olaraq View-ə uyğun istənilən tip qaytarılır: Text, Image, VStack, fərdi struktur. Kompilyator optimallaşdırma üçün kompilyasiya mərhələsində konkret tipi müəyyən edir.
some View — kompilyasiya mərhələsində konkret tipin müəyyən edilməsi ilə qeyri-şəffaf tip. AnyView — tip silmə (type erasure), istənilən View-i vahid konteynerə yerləşdirir. some View daha səmərəlidir, AnyView yük əlavə edir və yalnız dinamik tip dəyişməsi lazım olduqda istifadə olunur.
10 elementə qədər — bu, arilik 1-dən 10-a qədər buildBlock yaradan TupleView məhdudiyyətidir. Daha çox element lazımdırsa, Group, ForEach, List istifadə edin və ya alt komponentlərə bölün. Bu məhdudiyyət Swift kompilyatoru səviyyəsində mövcuddur.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun