Published on

SwiftUI crypto app — HomeView-da ro'yxatlar va ViewModel-ni sozlash

Authors

SwiftUI crypto app — HomeView-da ro'yxatlar va ViewModel-ni sozlash

Ushbu darsda biz ilovamizning MVVM arxitekturasini yaratishni boshlaymiz: ma'lumotlar bilan ishlovchi HomeViewModelni yozamiz va uni butun ilova bo'ylab tarqatish uchun EnvironmentObject mexanizmidan foydalanamiz.

Shuningdek, HomeViewda foydalanuvchining shaxsiy portfeli va umumiy bozor narxlari ro'yxatlarini chiroyli gorizontal animatsiya (transition) yordamida almashtirishni sozlaymiz.


1. HomeViewModel yaratish

home/viewmodels papkasi ichida HomeViewModel.swift nomli yangi fayl ochamiz. Bu klass ilova ma'lumotlarini boshqarishi uchun ObservableObject protokoliga moslanadi:

import Foundation
import Combine

class HomeViewModel: ObservableObject {

    // Ilovadagi barcha tangalar va foydalanuvchi portfelidagi tangalar ro'yxati
    @Published var allCoins: [CoinModel] = []
    @Published var portfolioCoins: [CoinModel] = []

    init() {
        // Tarmoqdan yuklashni simulyatsiya qilish uchun 2 soniyali kechikishdan foydalanamiz
        addSubscribers()
    }

    private func addSubscribers() {
        // Hozircha tarmoq ulanmaganligi uchun, 2 soniyadan keyin mock ma'lumotlarni ro'yxatlarga qo'shamiz
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            self.allCoins.append(DeveloperPreview.instance.coin)
            self.portfolioCoins.append(DeveloperPreview.instance.coin)
        }
    }
}

2. ViewModel-ni ilovaga va preview-ga integratsiya qilish

Biz bir nechta turli ekranlarda ayni bitta ma'lumotlar manbasidan foydalanamiz. Shuning uchun ViewModel obyektini bir marta yaratib, butun loyiha bo'ylab tarqatish uchun Environment Objectdan foydalanamiz.

App.swift faylida sozlash

@main
struct SwiftfulCryptoApp: App {

    // Asosiy ViewModel obyektini yaratamiz
    @StateObject private var vm = HomeViewModel()

    var body: some Scene {
        WindowGroup {
            NavigationView {
                HomeView()
                    .navigationBarHidden(true)
            }
            // Butun navigatsiya iyerarxiyasiga ViewModelni ulash
            .environmentObject(vm)
        }
    }
}

PreviewProvider uchun ulanish (PreviewProvider.swift)

DeveloperPreview klassiga ViewModel mock obyektini qo'shib qo'yamiz:

class DeveloperPreview {
    static let instance = DeveloperPreview()
    private init() {}

    let coin = CoinModel(...)
    // Mock ViewModel
    let homeVM = HomeViewModel()
}

3. HomeView-da ro'yxatlarni va animatsiyalarni shakllantirish

Endi HomeView.swift faylida ViewModel-ni @EnvironmentObject orqali chaqiramiz va allCoinsList hamda portfolioCoinsList ro'yxatlarini dizayn qilamiz.

Ro'yxatlar almashayotganda chapga va o'ngga surilishi uchun .transition(.move(edge: .leading)) va .transition(.move(edge: .trailing)) modifikatorlaridan foydalanamiz.

import SwiftUI

struct HomeView: View {

    // Atrof-muhitdan (Environment) ViewModelni qabul qilamiz
    @EnvironmentObject private var vm: HomeViewModel
    @State private var showPortfolio: Bool = false

    var body: some View {
        ZStack {
            Color.theme.background
                .ignoresSafeArea()

            VStack {
                homeHeader

                columnTitles

                if !showPortfolio {
                    // Umumiy narxlar ro'yxati (chapga suriladi)
                    allCoinsList
                        .transition(.move(edge: .leading))
                }

                if showPortfolio {
                    // Portfel ro'yxati (o'ngga suriladi)
                    portfolioCoinsList
                        .transition(.move(edge: .trailing))
                }

                Spacer(minLength: 0)
            }
        }
    }
}

4. Ro'yxat ustunlari nomlari (Column Titles) va ro'yxat qismlari

HomeView faylining ostida extension yaratib, ro'yxat elementlari va ustun nomlarini ajratib yozamiz. Bu body kodini o'qishni juda osonlashtiradi:

extension HomeView {

    // Ustun nomlari
    private var columnTitles: some View {
        HStack {
            Text("Coin")
            Spacer()
            if showPortfolio {
                Text("Holdings")
            }
            Text("Price")
                .frame(width: UIScreen.main.bounds.width / 3.5, alignment: .trailing)
        }
        .font(.caption)
        .foregroundColor(Color.theme.secondaryText)
        .padding(.horizontal)
    }

    // Barcha tangalar ro'yxati
    private var allCoinsList: some View {
        List {
            ForEach(vm.allCoins) { coin in
                CoinRowView(coin: coin, showHoldingsColumn: false)
                    .listRowInsets(.init(top: 10, leading: 0, bottom: 10, trailing: 10))
            }
        }
        .listStyle(.plain)
    }

    // Portfeldagi tangalar ro'yxati
    private var portfolioCoinsList: some View {
        List {
            ForEach(vm.portfolioCoins) { coin in
                CoinRowView(coin: coin, showHoldingsColumn: true)
                    .listRowInsets(.init(top: 10, leading: 0, bottom: 10, trailing: 10))
            }
        }
        .listStyle(.plain)
    }
}

Ushbu bosqichdan so'ng ilovani ishga tushirganimizda, 2 soniya davomida bo'sh ekran ko'rinadi va ma'lumotlar "yuklangach" ro'yxatda Bitcoin ko'rinadi. O'ngga surilganda esa portfeldagi Bitcoin va uning umumiy summasi ko'rsatiladi.

Keyingi darsda biz nihoyat internetdan (API) jonli ma'lumotlarni yuklab olishni boshlaymiz! 🚀

Buy mea coffee