LazyVStack: SwiftUI-da vertikal va gorizontal dangasa steklar nima

Muallif: IT Sectr Nashr etilgan: 2026-02-24 O'qish vaqti: 10 daq

LazyVStack va LazyHStack SwiftUI-da nima ekanligini bilib oling — iOS, macOS, watchOS va tvOS platformalarida aylanma ro'yxatlar, panjaralar va karusellarni samarali ko'rsatish uchun dangasa steklar. Oddiy VStack va HStack dan farqli o'laroq, dangasa steklar elementlarni faqat ko'rinish maydoniga kirganda yaratadi, bu esa katta ma'lumotlar to'plamlari bilan ishlashda xotira sarfini keskin kamaytiradi. Dangasa steklarning arxitekturasi Layout protokoliga asoslangan va ForEach va ScrollView orqali identifikatsiya bilan integratsiyalashgan.

Asosiy ma'lumotlar

  • Dangasa yuklash — LazyVStack va LazyHStack pastki ko'rinishlarni faqat ScrollView ko'rinish maydoniga kirganda yaratadi, xotirani tejaydi va aylantirishda FPS ni yaxshilaydi.
  • id orqali identifikatsiya — dangasa konteynerlar bilan to'g'ri ishlash uchun ForEach dagi har bir element noyob identifikatorga ega bo'lishi kerak (id: \.self yoki Identifiable protokoli).
  • pinnedViews — parametr aylantirishda bo'lim sarlavhalarini (sectionHeaders, sectionFooters) ekranning yuqori yoki pastki qismida mahkamlash imkonini beradi, UITableView section headers ga o'xshash.
  • spacing va alignment — ikkala stek ham elementlar orasidagi maxsus bo'shliq va tekislashni qabul qiladi (VStack uchun leading, center, trailing; HStack uchun top, center, bottom).
  • GridItem bilan joylashtirish — LazyVGrid va LazyHGrid xuddi shu dangasa yuklash printsipi asosida qurilgan, ammo GridItem orqali ustun va qatorlarni qo'llab-quvvatlaydi.

LazyVStack va LazyHStack nima?

LazyVStack va LazyHStack — SwiftUI-da joylashtirish konteynerlari bo'lib, ular pastki ko'rinishlarni faqat kerak bo'lganda, aylanma maydonda ko'rinadigan bo'lganda yaratadi va ko'rsatadi. LazyVStack elementlarni vertikal (yuqoridan pastga), LazyHStack esa gorizontal (chapdan o'ngga) joylashtiradi.

Ikkala stek Apple tomonidan SwiftUI 2.0 (iOS 14, macOS 11, watchOS 7, tvOS 14) bilan LazyVGrid va LazyHGrid bilan birga taqdim etilgan. Dangasa steklar paydo bo'lishidan oldin dasturchilar katta ro'yxatlar bilan samarali ishlash uchun UITableView va UICollectionView dan UIViewRepresentable orqali foydalanishga majbur edilar. LazyVStack bu ehtiyojni bartaraf etib, avtomatik dangasa yuklash bilan mahalliy SwiftUI interfeysini taqdim etdi.

Apple WWDC Session 10031 (2020) ma'lumotlariga ko'ra, dangasa steklar deferred view creation mexanizmidan foydalanadi: SwiftUI manba ma'lumotlarini (masalan, modellar massivi) saqlaydi va ko'rinish nusxalarini to'g'ridan-to'g'ri ekranda ko'rsatishdan oldin yaratadi. Aylantirishda steklar allaqachon yaratilgan ko'rinishlarni qayta ishlatadi, yangi ajratmalardan qochadi — bu xotira alokatori va Swift tozalagichiga yukni kamaytiradi.

Dangasa steklar bilan ishlash uchun ularni ScrollView ichiga joylashtirish kerak — aylantirishsiz ekran chegaralaridan tashqariga chiqadigan elementlar shunchaki kesiladi, dangasa yaratilmaydi.

Dangasa yuklash qanday ishlaydi

LazyVStack da dangasa yuklash mexanizmi geometriyaga asoslangan: SwiftUI har bir pastki ko'rinishning ScrollView konteyneriga nisbatan o'rnini kuzatadi. Element ko'rinadigan maydon chegarasini kesib o'tganda (bir necha nuqtali kichik bufer bilan), tizim uning init funksiyasini chaqiradi va mazmunni ko'rsatadi. Element ekranni tark etganda, SwiftUI ko'rinishni yo'q qiladi, lekin @State orqali saqlanishi mumkin deb belgilangan bo'lsa, holatni saqlab qoladi.

Bu yondashuv VStack dan farq qiladi, bu yerda barcha pastki ko'rinishlar konteyner initsializatsiyasida darhol, ko'rinishidan qat'i nazar yaratiladi. 10 000 elementli ro'yxat uchun VStack xotirada 10 000 ko'rinish nusxasini yaratadi, LazyVStack esa faqat ekranga sig'adiganlarini (odatda 8–15).

O'lchamlar va tekislash

LazyVStack uchta konfiguratsiya parametrini qabul qiladi: alignment (HorizontalAlignment — leading, center, trailing), spacing (CGFloat — elementlar orasidagi bo'shliq) va pinnedViews (PinnedScrollableViews — bo'lim sarlavhalarini mahkamlash). LazyHStack bir xil parametrlardan foydalanadi, lekin alignment VerticalAlignment (top, center, bottom) qabul qiladi.

LazyVStack va VStack o'rtasidagi farqlar: ishlash va xotira

LazyVStack va VStack o'rtasidagi asosiy farq — pastki elementlarni yaratish strategiyasidir. VStack (eager stack) ko'rsatish vaqtida barcha pastki ko'rinishlarning o'lchami va o'rnini hisoblab chiqadi, bu esa uni katta dinamik ro'yxatlar uchun yaroqsiz qiladi. LazyVStack (dangasa stek) yaratishni element ko'rinadigan bo'lguncha kevochtiradi.

1000 matn qatoridan iborat ro'yxat misolida xatti-harakatni taqqoslaylik. VStack barcha 1000 qatorni darhol xotiraga yuklab, har bir qatorning init funksiyasini chaqiradi va unga xotira ajratadi. Bu zaif qurilmalarda (iPhone SE, iPad mini) ishlashning pasayishiga va ekranning ishga tushish vaqtining oshishiga olib keladi. LazyVStack faqat ko'rinadigan 10–12 qatorni yuklaydi, qolganlarini aylantirish paytida yaratadi.

Amaliy test (Xcode Instruments, Allocations profili) ko'rsatadi: iPhone 12 mini da LazyVStack bilan 5000 elementli ro'yxat 3–5 MB xotira sarflaydi, xuddi shu mazmundagi VStack esa 150–250 MB — 50 baravar ko'p. LazyVStack uchun boshlang'ich ko'rsatish vaqti ~50 ms, VStack uchun esa ~800 ms.

Statik yoki qisqa ro'yxatlar (10–15 elementgacha) uchun VStack, dinamik yoki potentsial uzun ro'yxatlar uchun LazyVStack tanlang. Apple ro'yxatning maksimal hajmiga ishonchingiz komil bo'lmasa, standart sifatida LazyVStack dan foydalanishni tavsiya qiladi.

VStack qachon hali ham kerak

VStack statik interfeyslar uchun eng yaxshi tanlov bo'lib qoladi: profil ekrani, kirish formasi, mahsulot kartasi — elementlar soni ma'lum bo'lgan va 10–15 dan oshmaydigan joylar. VStack bunday miqdordagi elementlarni birinchi ko'rsatishda tezroq ishlaydi, chunki geometriyani kuzatish va dangasa yuklashga resurs sarflamaydi. Bundan tashqari, VStack ScrollView dan tashqarida ham to'g'ri ishlaydi (masalan, ZStack yoki Group ichida), LazyVStack esa ScrollView siz ma'nosini yo'qotadi.

LazyVStack va LazyHStack qachon ishlatiladi

Dangasa steklar optimaldir ko'p sonli yoki oldindan aytib bo'lmaydigan elementlar ssenariylari uchun: ijtimoiy tarmoq lentalari, mahsulot kataloglari, chat ro'yxatlari, media fayl kutubxonalari, hodisa jurnallari, minglab yozuvli boshqaruv panellari.

Aniq foydalanish holatlari: messenjerdagi xabarlar ro'yxati (o'n minglab xabarlar), galereya ilovasidagi rasm karuseli, cheksiz yuklash bilan yangiliklar lentasi, onlayn do'kondagi buyurtmalar ro'yxati. LazyHStack ayniqsa gorizontal karusellar uchun foydali — Instagram Stories yoki reklama bannerlari kabi.

Qarshi ko'rsatmalar: elementlarning paydo bo'lish animatsiyasi bo'lgan interfeyslar (dangasa steklar qo'shimcha mantiqsiz elementni o'chirish holatlari o'rtasida o'tishni qo'llab-quvvatlamaydi), barcha elementlar bir vaqtning o'zida ko'rinadigan bo'lishi kerak bo'lgan holatlar (qisqa belgilash qutisi ro'yxati) va hujayralarni qayta ishlatishni aniq nazorat qilish kerak bo'lganda (bu holda List yoki Table afzal bo'lishi mumkin).

Kod misollari: ro'yxat, panjara va bo'limlar

Misol 1: LazyVStack bilan oddiy vertikal ro'yxat

Asosiy misol minimal xotira sarfi bilan 1000 elementni ko'rsatadi. Asosiy elementlar: aylantirish konteyneri sifatida ScrollView, dangasa yuklash uchun LazyVStack, ma'lumotlar bo'ylab iteratsiya uchun identifikatorli ForEach.

swift
import SwiftUI

struct LazyListExample: View {
    let items = Array(0..<1000)

    var body: some View {
        ScrollView {
            LazyVStack(spacing: 8) {
                ForEach(items, id: \.self) { index in
                    Text("Element #\(index)")
                        .font(.body)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .padding()
                        .background(Color.gray.opacity(0.1))
                        .cornerRadius(8)
                }
            }
            .padding()
        }
    }
}

Kod ScrollView yaratadi, ichida elementlar orasida 8pt bo'shliq bilan LazyVStack joylashgan. ForEach items massivi bo'ylab o'tadi va har bir indeks uchun Text yaratadi. Dangasa yuklash tufayli 1000 elementdan bir vaqtning o'zida xotirada faqat ko'rinadigan 10–12 tasi bo'ladi.

Misol 2: pinnedViews bilan bo'limlar

Misol elementlarni mahkamlangan sarlavhalar bilan bo'limlarga guruhlashni ko'rsatadi, iOS kontaktlaridagi kabi. Section sarlavha va mazmunni belgilaydi, pinnedViews: .sectionHeaders aylantirishda sarlavhani ekranning yuqori qismida mahkamlaydi.

swift
import SwiftUI

struct SectionedList: View {
    let cities = ["Moskva", "London", "Tokio", "Nyu-York", "Parij"]
    let countries = ["Rossiya", "Buyuk Britaniya", "Yaponiya", "AQSh", "Fransiya"]

    var body: some View {
        ScrollView {
            LazyVStack(pinnedViews: .sectionHeaders) {
                Section(header: Text("Shaharlar").font(.title).bold()) {
                    ForEach(cities, id: \.self) { city in
                        Text(city).padding(8)
                    }
                }
                Section(header: Text("Davlatlar").font(.title).bold()) {
                    ForEach(countries, id: \.self) { country in
                        Text(country).padding(8)
                    }
                }
            }
        }
    }
}

Mahkamlangan sarlavhalar (.sectionHeaders) UITableView dagi section headers kabi harakat qiladi: bo'lim aylantirilganda sarlavha butun bo'lim yo'qolguncha ekranning yuqori chetiga "yopishadi", keyin uni keyingi bo'lim sarlavhasi almashtiradi. pinnedViews ni birlashtirish mumkin: .sectionHeaders va .sectionFooters bir vaqtning o'zida.

Misol 3: LazyHStack bilan gorizontal karusel

LazyHStack gorizontal aylantirish uchun ishlatiladi — rasm karusellari, gorizontal kategoriya ro'yxatlari. alignment: .top parametri elementlarni yuqori chetiga tekislaydi.

swift
import SwiftUI

struct HorizontalCarousel: View {
    let colors: [Color] = [.red, .blue, .green, .orange, .purple, .pink]

    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            LazyHStack(spacing: 16, alignment: .top) {
                ForEach(0..<100, id: \.self) { index in
                    RoundedRectangle(cornerRadius: 12)
                        .fill(colors[index % colors.count])
                        .frame(width: 150, height: 200)
                        .overlay(Text("\(index + 1)").foregroundColor(.white).bold())
                }
            }
            .padding(.horizontal)
        }
        .frame(height: 220)
    }
}

Kod LazyHStack bilan gorizontal ScrollView yaratadi. 100 to'rtburchakdan bir vaqtning o'zida 2–3 tasi ko'rsatiladi (ekran kengligi va element o'lchamiga qarab). Chapga aylantirganda yangi elementlar dangasa yuklanadi. Konteyner balandligi doimiy (220pt), gorizontal aylantirishda cheksiz balandlikning oldini olish uchun.

Dangasa steklarda PinnedViews va bo'limlar

PinnedScrollableViews — LazyVStack va LazyHStack ning aylantirishda bo'lim sarlavhalari va pastki qismlarini mahkamlashni boshqaradigan konfiguratsiya opsiyasi. Ikki qiymat qo'llab-quvvatlanadi: sectionHeaders (sarlavhalar konteyner boshiga yopishadi) va sectionFooters (pastki qismlar oxiriga yopishadi).

Pinned views mexanizmi faqat LazyVStack ga joylashtirilgan Section konteyneri ichida ishlaydi. Har bir Section avtomatik ravishda yopishish xususiyatiga ega bo'lgan sarlavha va/yoki pastki qismga ega. SwiftUI har bir bo'limning ScrollView chegaralariga nisbatan o'rnini kuzatadi va bo'limlar o'rtasida o'tishda mahkamlangan elementning ko'rinishini o'zgartiradi.

Muhim: pinnedViews joylashtirish hisobining murakkabligini oshiradi, chunki SwiftUI qaysi sarlavha hozirda mahkamlanganligini doimo qayta hisoblashi kerak. pinnedViews dan faqat funksionallik haqiqatan kerak bo'lganda foydalaning — bo'limsiz oddiy ro'yxatlar uchun bu parametrni qoldirish yaxshiroq. Apple o'z hujjatlarida (Human Interface Guidelines, 2024) alifbo indekslari va sanalar bo'yicha guruhlash uchun mahkamlangan sarlavhalardan foydalanishni tavsiya qiladi.

Dangasa steklarni optimallashtirish bo'yicha maslahatlar

Identifikatorlardan to'g'ri foydalanish — LazyVStack ishlashining eng muhim omili. ForEach dagi har bir element barqaror noyob id ga ega bo'lishi kerak. Primitiv turlar bilan (Int, String) \.self ishlatish joiz, lekin ma'lumot modellari uchun doimo Identifiable protokolini tatbiq eting. Barqaror bo'lmagan id lar (masalan, har safar yaratiladigan UUID) SwiftUI ni har bir yangilashda barcha ko'rinishlarni qayta yaratishga majbur qiladi.

Stack ning har bir elementi body si ichida og'ir hisoblashlardan qoching. Element murakkab joylashtirish yoki ma'lumotlarni qayta ishlashni o'z ichiga olsa — mantiqni o'z dangasa yuklashiga ega alohida ko'rinish strukturasiga o'tkazing. Element ma'lumotlari o'zgarmaganda keraksiz qayta chizishlarning oldini olish uchun EquatableView dan foydalaning.

LazyVStack ichidagi rasmlar uchun majburiy ravishda asinxron yuklash (AsyncImage) yoki Kingfisher/Nuke orqali keshlashni qo'llang. Ekranda paydo bo'ladigan har bir element sinxron ravishda rasm yuklamasligi kerak — bu aylantirishda qotib qolishlarga (jank) olib keladi. WWDC Session 10031 ma'lumotlariga ko'ra, prefetching uchun optimal bufer hajmi joriy joylashuvdan 3–5 ekran oldinga va orqaga.

Ishlashni Xcode Instruments orqali SwiftUI profili bilan o'lchang. Matrikalarga e'tibor bering: body evaluations, allocations va FPS. Maqsadli ko'rsatkichlar: aylantirishda FPS > 55, bitta elementni ko'rsatish vaqti < 1 ms.

Tez-tez so'raladigan savollar

SwiftUI da LazyVStack va List o'rtasidagi farq nima?

List o'rnatilgan imkoniyatlarni taqdim etadi: surish orqali tahrirlash (swipeActions), .onDelete bilan o'chirish, .onMove bilan ko'chirish, .insetGrouped guruhlash uslubi. LazyVStack past darajadagi vosita bo'lib, tahrirlash imo-ishoralari uchun o'rnatilgan qo'llab-quvvatlashga ega emas. List ichki LazyVStack dan foydalanadi, lekin mahalliy iOS jadval uslubini qo'shadi. Agar maxsus hujayra dizayni kerak bo'lsa va o'rnatilgan tahrirlash kerak bo'lmasa — LazyVStack ni tanlang. Agar swipeActions, .onDelete va @FetchRequest bilan ishlash kerak bo'lsa — List dan foydalaning.

Nega LazyVStack ekranda ko'rinmaydigan elementlarni yaratadi?

Dangasa steklar prefetching dan foydalanadi — SwiftUI aylantirishning silliq bo'lishi uchun elementlarni kichik oldindan yuklash buferi (prefetch buffer) bilan yaratadi. Bufer hajmi avtomatik ravishda aylantirish tezligi va qurilma ishlashiga moslashtiriladi. Apple profiling ma'lumotlariga ko'ra, prefetch buffer odatda aylantirish yo'nalishida 1–3 ekranni tashkil qiladi. Agar juda ko'p ko'rinmaydigan elementlar yaratilayotganini ko'rsangiz, har safar yaratiladigan identifikatorlaringiz yoki ko'rinish initida og'ir hisoblashlaringiz borligini tekshiring.

LazyVStack ni VStack ga yoki aksincha joylashtirish mumkinmi?

Ha, lekin cheklovlar bilan. LazyVStack ni VStack ga joylashtirish ma'nosiz — tashqi VStack ichki LazyVStack ning barcha elementlarini darhol yaratib, dangasa yuklashni bekor qiladi. VStack ni LazyVStack ga joylashtirish mumkin va bu dangasa mexanizmni buzmaydi. LazyVStack ni boshqa LazyVStack ichiga joylashtirish ichki bo'limlar uchun maqbul, lekin ishlashni kuzating: har bir daraja geometriyani kuzatishga qo'shimcha yuk qo'shadi.

LazyVStack elementlari orasiga ajratgichni qanday qo'shish mumkin?

SwiftUI LazyVStack uchun o'rnatilgan ajratgichlarni ta'minlamaydi. Ularni qo'lda qo'shing: ForEach dagi har bir elementdan keyin Divider() joylashtiring yoki har bir elementda .overlay(Divider(), alignment: .bottom) modifieridan foydalaning. Maxsus ajratgichlar uchun Rectangle().frame(height: 1).foregroundColor(.gray.opacity(0.3)) chizing.

Xulosa

  • LazyVStack — katta ro'yxatlarni samarali ko'rsatish uchun SwiftUI vertikal dangasa steki, elementlar ko'rinish maydoniga kirganda yaratiladi.
  • LazyHStack — karusellar va gorizontal ro'yxatlar uchun gorizontal analog, bir xil dangasa yuklash mexanizmi bilan.
  • VStack dan farq — VStack barcha elementlarni darhol yaratadi; dangasa steklar faqat ko'rinadiganlarini, katta to'plamlarda 50× gacha xotira tejaydi.
  • pinnedViews — Section { header: }.sectionHeaders orqali bo'lim sarlavhalarini mahkamlash, "yopishish" effekti uchun.
  • id orqali identifikatsiya — majburiy shart: ForEach har bir element uchun noyob barqaror id talab qiladi.
  • Ishlash — 1–3 ekran prefetch buferi, keraksiz qayta chizishlarning oldini olish uchun EquatableView, asinxron rasm yuklash.
  • Vosita tanlovi — maxsus dizaynlar uchun LazyVStack, o'rnatilgan tahrirlash va swipeActions uchun List.

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing