Published on

SwiftUI-da Core Data va @FetchRequest bilan ishlash

Authors

Bu videoda Core Data ko'rib chiqiladi. Bu — iPhone ichida saqlanadigan to'liq ma'lumotlar bazasi. Foydalanuvchi ilovani yopib qayta ochsa ham, ma'lumotlar o'chib ketmaydi.


Core Data vs UserDefaults

UserDefaults / AppStorageCore Data
MaqsadKichik ma'lumotlar (ism, sozlama)Katta hajmdagi ma'lumotlar bazasi
SaqlashKalit-qiymatJadval (entity) shaklida
Qidiruv va saralashYo'qNSSortDescriptor, NSPredicate
Qachon ishlatishOddiy sozlamalarRo'yxatlar, ilovaning asosiy ma'lumotlari

1-qadam: Yangi loyihada Core Data yoqish

Xcode-da yangi loyiha yaratishda: Use Core Data katagini belgilash. Apple avtomatik quyidagilarni yaratib beradi:

  • Persistence.swift — ma'lumotlar bazasini boshqaruvchi fayl
  • .xcdatamodeld — entity va atributlar sxemasi
  • Tayyor ContentView — oddiy misol

Arxitektura — asosiy komponentlar

PersistenceController — Singleton

struct PersistenceController {

    // Singleton — butun ilova bo'ylab bitta instance
    static let shared = PersistenceController()

    // Preview uchun alohida instance
    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext

        // Preview uchun soxta ma'lumotlar
        for x in 0..<10 {
            let newFruit = FruitEntity(context: viewContext)
            newFruit.name = "Apple \(x)"
        }
        try? viewContext.save()
        return result
    }()

    // NSPersistentContainer — ma'lumotlar bazasi o'zi
    let container: NSPersistentContainer

    init(inMemory: Bool = false) {
        // Nom = .xcdatamodeld fayl nomi bilan bir xil bo'lishi shart
        container = NSPersistentContainer(name: "CoreDataBootcamp")

        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }

        container.loadPersistentStores { _, error in
            if let error = error {
                // Development vaqtida crash qilish — xato bor bo'lsa darhol bildirish
                // Production-da bu qatorni olib tashlash tavsiya etiladi
                fatalError("Xato: \(error.localizedDescription)")
            }
        }
    }
}

App.swift — viewContext-ni muhitga qo'yish

@main
struct CoreDataBootcampApp: App {

    let persistenceController = PersistenceController.shared

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(
                    \.managedObjectContext,
                    persistenceController.container.viewContext
                )
        }
    }
}

viewContext — ma'lumotlar bazasidagi aktiv ish maydoni. Barcha o'qish, yozish va o'chirish shu context orqali amalga oshiriladi.


2-qadam: FruitEntity yaratish

.xcdatamodeld faylida:

  1. Mavjud Item entity-ni o'chirish
  2. Add EntityFruitEntity deb nomlash
  3. Add Attributename, turi String

Saqlash mumkin bo'lgan turlar: String, Int16/32/64, Double, Float, Bool, Date, UUID, Binary Data. Rasm yoki rang to'g'ridan-to'g'ri saqlanmaydi — Binary Data-ga konvertatsiya qilish kerak.

Xcode entity yaratilgandan so'ng, Xcode-ni qayta ishga tushirish tavsiya etiladi — ba'zan yangi entity avtomatik topilmaydi.


3-qadam: @FetchRequest — ma'lumotlarni olish

struct ContentView: View {

    // muhitdan viewContext olish
    @Environment(\.managedObjectContext) private var viewContext

    // FruitEntity-larni ma'lumotlar bazasidan olish
    @FetchRequest(
        entity: FruitEntity.entity(),
        sortDescriptors: [
            NSSortDescriptor(
                keyPath: \FruitEntity.name,
                ascending: true  // A → Z tartibda
            )
        ]
    ) var fruits: FetchedResults<FruitEntity>

    @State private var textFieldText: String = ""

    var body: some View {
        NavigationView {
            VStack(spacing: 20) {

                // Kiritish maydoni
                TextField("Meva nomini kiriting...", text: $textFieldText)
                    .font(.headline)
                    .padding(.leading)
                    .frame(height: 55)
                    .frame(maxWidth: .infinity)
                    .background(Color(.systemGray5))
                    .cornerRadius(10)
                    .padding(.horizontal)

                // Qo'shish tugmasi
                Button {
                    addItem()
                } label: {
                    Text("Qo'shish")
                        .font(.headline)
                        .foregroundColor(.white)
                        .frame(height: 55)
                        .frame(maxWidth: .infinity)
                        .background(Color.blue)
                        .cornerRadius(10)
                }
                .padding(.horizontal)

                // Mevalar ro'yxati
                List {
                    ForEach(fruits) { fruit in
                        Text(fruit.name ?? "")
                            .onTapGesture {
                                updateItem(fruit: fruit)
                            }
                    }
                    .onDelete(perform: deleteItems)
                }
                .listStyle(PlainListStyle())
            }
            .navigationTitle("Mevalar ro'yxati")
            .navigationBarItems(leading: EditButton())
        }
        .onAppear {
            // Ilova ochilganda ma'lumotlar @FetchRequest orqali avtomatik yuklanadi
        }
    }
}

CRUD funksiyalari

Create — qo'shish

private func addItem() {
    withAnimation {
        // Yangi entity yaratish
        let newFruit = FruitEntity(context: viewContext)
        newFruit.name = textFieldText  // textFieldText qiymatini saqlash

        // Saqlash va textField-ni tozalash
        saveItems()
        textFieldText = ""
    }
}

Read — o'qish

@FetchRequest bu ishni avtomatik bajaradi — fruits massivi doim yangilanib turadi. Qo'shimcha kod shart emas.

Update — yangilash

private func updateItem(fruit: FruitEntity) {
    withAnimation {
        // Entity-ni bevosita tahrirlash
        let currentName = fruit.name ?? ""
        let newName = currentName + "!"  // Misol: "Apple" → "Apple!"
        fruit.name = newName

        // Saqlash
        saveItems()
    }
}

Delete — o'chirish

private func deleteItems(offsets: IndexSet) {
    withAnimation {
        // IndexSet-dan birinchi indexni olish
        guard let index = offsets.first else { return }

        let fruitEntity = fruits[index]
        viewContext.delete(fruitEntity)

        saveItems()
    }
}

Save — saqlash (umumiy funksiya)

private func saveItems() {
    do {
        try viewContext.save()
    } catch {
        // Production-da bu yerda fatalError emas, xatoni log qilish tavsiya etiladi
        fatalError("Saqlash xatosi: \(error.localizedDescription)")
    }
}

NSSortDescriptor — tartiblash

// A → Z tartibda
NSSortDescriptor(keyPath: \FruitEntity.name, ascending: true)

// Z → A tartibda
NSSortDescriptor(keyPath: \FruitEntity.name, ascending: false)

// Bir nechta mezon bo'yicha
sortDescriptors: [
    NSSortDescriptor(keyPath: \FruitEntity.name, ascending: true),
]

@FetchRequest va MVVM

Bu videoda barcha logika View ichida yozildi — bu boshlang'ich uchun tushunish osonroq. Lekin professional ilovalarda bu yondashuv MVVM arxitekturasiga to'g'ri kelmaydi: View-da faqat UI bo'lishi kerak, ma'lumot logikasi esa ViewModel-da bo'lishi kerak.

Bu video:    View = UI + @FetchRequest + CRUD funksiyalari
MVVM usuli:  View = faqat UI
             ViewModel = @FetchRequest + CRUD funksiyalari

Keyingi videoda xuddi shu Core Data logikasi MVVM arxitekturasi bilan qayta yoziladi.


Xulosa

QadamNima qilinadi
Yangi loyiha"Use Core Data" belgilash
Persistence.swiftPersistenceController (Singleton) + container
App.swiftviewContext-ni muhitga qo'yish
.xcdatamodeldEntity va atributlar yaratish
View@Environment(\.managedObjectContext) + @FetchRequest
CRUDaddItem, deleteItems, updateItem, saveItems

Core Data — katta hajmdagi ma'lumotlarni qurilmada doimiy saqlash uchun kuchli va samarali vosita. Sessiyalar orasida saqlanishi, saralash va filtrlash imkoniyatlari uni real ilovalarda asosiy ma'lumot ombori sifatida ishlatishga imkon beradi.

Buy mea coffee