Published on

Todo List ilovasi β€” Vazifalar ro'yxati view-ini yaratish

Authors

MVVM (Model-View-ViewModel) arxitekturasida View β€” bu foydalanuvchi ko'radigan va o'zaro ta'sirlashadigan UI mantig'i. Bu videoda ikkita asosiy view yaratiladi: vazifalar ro'yxatini ko'rsatuvchi ListView va yangi vazifa qo'shish uchun AddView.


MVVM arxitekturasi β€” qisqacha

  • Model (M) β€” ma'lumot nuqtasi (data point)
  • View (V) β€” foydalanuvchi interfeysi, SwiftUI kodi
  • ViewModel (VM) β€” ObservableObject klassi, model va view orasidagi vositachi, ma'lumotlarni boshqaradi

Yangi loyiha yaratish

Xcode-da yangi loyiha yaratishda quyidagi sozlamalar tanlanadi:

  • Platforma: iOS (faqat iPhone va iPad)
  • Interfeys: SwiftUI
  • Life cycle: SwiftUI App
  • Til: Swift
  • Core Data: o'chirilgan
  • Tests: o'chirilgan

Mahsulot nomi (Product Name) bo'sh joysiz, camelCase uslubida kiritiladi β€” masalan, ToDoList.


Loyiha tuzilmasini sozlash

Navigator-da yangi guruhlar yaratiladi β€” MVVM tuzilmasiga mos:

Views/
Models/
ViewModels/

Standart ContentView fayli o'chiriladi, chunki u o'rniga maxsus view-lar yaratiladi.


Butun ilovani NavigationView ichiga olish

App faylida butun ilova bitta NavigationView ichiga joylashtiriladi β€” shunda barcha ekranlar avtomatik navigatsiya muhitida bo'ladi:

@main
struct ToDoListApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationView {
                ListView()
            }
        }
    }
}

ListView β€” vazifalar ro'yxati

Views papkasida yangi SwiftUI fayli yaratiladi β€” ListView.

Preview-ni haqiqiy ilova muhitiga moslashtirish uchun uni ham NavigationView ichiga o'raladi:

struct ListView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            ListView()
        }
    }
}

Asosiy List komponenti

struct ListView: View {
    var body: some View {
        List {
            Text("Salom")
        }
        .navigationTitle("Vazifalar ro'yxati πŸ“")
    }
}

Ro'yxat qatori β€” ListRowView

Har bir vazifa belgisi (check mark) va sarlavhadan iborat bo'ladi:

HStack {
    Image(systemName: "checkmark.circle")

    Text("Birinchi element")

    Spacer()
}

Bu qator bir necha marta turli ma'lumotlar bilan ishlatilishi kerak bo'lgani uchun, u alohida komponentga ajratiladi (Extract Subview orqali yoki qo'lda) va alohida faylga ko'chiriladi β€” ListRowView.

Dinamik sarlavha bilan

struct ListRowView: View {

    let title: String

    var body: some View {
        HStack {
            Image(systemName: "checkmark.circle")
            Text(title)
            Spacer()
        }
    }
}

Preview:

struct ListRowView_Previews: PreviewProvider {
    static var previews: some View {
        ListRowView(title: "Birinchi sarlavha")
    }
}

Ma'lumotlar massivi bilan ro'yxatni to'ldirish

ListView-da vaqtinchalik String massivi yaratiladi (keyingi videoda bu to'liq model bilan almashtiriladi):

struct ListView: View {

    @State var items: [String] = [
        "Birinchi sarlavha",
        "Ikkinchi sarlavha",
        "Uchinchi"
    ]

    var body: some View {
        List {
            ForEach(items, id: \.self) { item in
                ListRowView(title: item)
            }
        }
        .navigationTitle("Vazifalar ro'yxati πŸ“")
    }
}

navigationBarItems orqali yuqori chap (leading) va o'ng (trailing) tugmalar qo'shiladi:

List {
    ForEach(items, id: \.self) { item in
        ListRowView(title: item)
    }
}
.navigationTitle("Vazifalar ro'yxati πŸ“")
.navigationBarItems(
    leading: EditButton(),
    trailing: NavigationLink("Qo'shish", destination: Text("Manzil"))
)
  • EditButton() β€” Xcode-ning tayyor tahrirlash tugmasi
  • NavigationLink β€” bosilganda yangi ekranga o'tadi

Ro'yxat stilini sozlash

Navigatsiya tugmalari qo'shilganda ro'yxat ko'rinishi avtomatik o'zgaradi. Standart ko'rinishni saqlash uchun:

List {
    ForEach(items, id: \.self) { item in
        ListRowView(title: item)
    }
}
.listStyle(PlainListStyle())

AddView β€” yangi vazifa qo'shish ekrani

Views papkasida yangi fayl β€” AddView yaratiladi:

struct AddView: View {

    @State var textFieldText: String = ""

    var body: some View {
        ScrollView {
            VStack {
                TextField("Shu yerga yozing...", text: $textFieldText)
                    .padding(.horizontal)
                    .frame(height: 55)
                    .background(Color(red: 0.9, green: 0.9, blue: 0.9))
                    .cornerRadius(10)

                Button(action: {
                    // hozircha bo'sh
                }, label: {
                    Text("SAQLASH")
                        .foregroundColor(.white)
                        .font(.headline)
                        .frame(maxWidth: .infinity)
                        .frame(height: 55)
                        .background(Color.accentColor)
                        .cornerRadius(10)
                })
            }
            .padding(14)
        }
        .navigationTitle("Vazifa qo'shish βœ’οΈ")
    }
}

Preview:

struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            AddView()
        }
    }
}

ListView-ni AddView bilan bog'lash

ListView-dagi NavigationLink manzili (destination) AddView()-ga almashtiriladi:

.navigationBarItems(
    leading: EditButton(),
    trailing: NavigationLink("Qo'shish", destination: AddView())
)

Endi "Qo'shish" tugmasi bosilganda AddView ekraniga o'tiladi, orqaga qaytish tugmasi esa NavigationView tomonidan avtomatik beriladi.


To'liq kod

// ListView.swift
struct ListView: View {

    @State var items: [String] = [
        "Birinchi sarlavha",
        "Ikkinchi sarlavha",
        "Uchinchi"
    ]

    var body: some View {
        List {
            ForEach(items, id: \.self) { item in
                ListRowView(title: item)
            }
        }
        .listStyle(PlainListStyle())
        .navigationTitle("Vazifalar ro'yxati πŸ“")
        .navigationBarItems(
            leading: EditButton(),
            trailing: NavigationLink("Qo'shish", destination: AddView())
        )
    }
}

// ListRowView.swift
struct ListRowView: View {

    let title: String

    var body: some View {
        HStack {
            Image(systemName: "checkmark.circle")
            Text(title)
            Spacer()
        }
    }
}

// AddView.swift
struct AddView: View {

    @State var textFieldText: String = ""

    var body: some View {
        ScrollView {
            VStack {
                TextField("Shu yerga yozing...", text: $textFieldText)
                    .padding(.horizontal)
                    .frame(height: 55)
                    .background(Color(red: 0.9, green: 0.9, blue: 0.9))
                    .cornerRadius(10)

                Button(action: {}, label: {
                    Text("SAQLASH")
                        .foregroundColor(.white)
                        .font(.headline)
                        .frame(maxWidth: .infinity)
                        .frame(height: 55)
                        .background(Color.accentColor)
                        .cornerRadius(10)
                })
            }
            .padding(14)
        }
        .navigationTitle("Vazifa qo'shish βœ’οΈ")
    }
}

Xulosa

Bu videoda yaratildi:

  • Loyiha tuzilmasi β€” Views, Models, ViewModels papkalari
  • ListView β€” vazifalar ro'yxatini ko'rsatuvchi asosiy ekran
  • ListRowView β€” qayta ishlatiluvchi ro'yxat qatori komponenti
  • AddView β€” yangi vazifa qo'shish uchun matn maydoni va saqlash tugmasi bilan ekran
  • Ikki ekran NavigationLink orqali bog'landi

Keyingi videoda Model qismi yaratiladi β€” oddiy String massivi o'rniga to'liq vazifa modeli ishlatiladi.


Keyingi videoda model qismini quramiz.

Buy mea coffee