Data Persistence
Cheat Sheet'lar
Data Persistence Cheat Sheet
iOS ilovalarda ma'lumotlarni lokal saqlash: UserDefaults, Keychain, FileManager, SwiftData va Core Data bo'yicha amaliy ma'lumotnoma.
1. Texnologiyalar Taqqoslash Jadvali
| Texnologiya | Qachon ishlatiladi? | Xavfsizlik darajasi | Ma'lumot hajmi |
|---|---|---|---|
| UserDefaults | Kichik sozlamalar, flaglar (isOnboardingShown) | Past (shifrlanmagan .plist) | < 1-2 MB |
| Keychain | Parollar, API/JWT tokenlar, biometriya sirlari | Eng yuqori (Hardware Secure Enclave) | Kichik matnlar |
| FileManager | Fayllar, PDF, rasmlar, offline audio/video | Standart fayl tizimi | Cheklanmagan (Disk hajmicha) |
| SwiftData | Yangi loyihalar (iOS 17+), relyatsion ma'lumotlar | Standart SQLite shifri | Katta hajmlar |
| Core Data | Katta korporativ loyihalar, iOS 16 va undan oldingi | Standart SQLite shifri | Katta hajmlar |
2. UserDefaults va @AppStorage
// Swift Standard
UserDefaults.standard.set(true, forKey: "is_logged_in")
UserDefaults.standard.set("dark", forKey: "app_theme")
let isLoggedIn = UserDefaults.standard.bool(forKey: "is_logged_in")
let theme = UserDefaults.standard.string(forKey: "app_theme") ?? "light"
// SwiftUI @AppStorage
struct SettingsView: View {
@AppStorage("hasSeenOnboarding") private var hasSeenOnboarding = false
var body: some View {
Toggle("Onboarding", isOn: $hasSeenOnboarding)
}
}
3. Keychain (Maxfiy Ma'lumotlar)
Keychain ma'lumotlari ilova o'chirilganda ham o'chib ketmaydi va zaxira nusxalarda shifrlangan bo'ladi.
import Security
enum KeychainService {
static func save(key: String, data: Data) -> Bool {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecValueData as String: data,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
SecItemDelete(query as CFDictionary) // Eskisini tozalash
return SecItemAdd(query as CFDictionary, nil) == errSecSuccess
}
static func load(key: String) -> Data? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
guard SecItemCopyMatching(query as CFDictionary, &item) == errSecSuccess else { return nil }
return item as? Data
}
static func delete(key: String) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key
]
SecItemDelete(query as CFDictionary)
}
}
4. FileManager (Fayl Tizimi)
final class LocalFileManager {
static let shared = LocalFileManager()
// Hujjatlar papkasi (iCloud backup'ga kiradi)
private var documentsDirectory: URL {
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
}
// Kesh papkasi (Tizim joy yetishmaganda avtomatik tozalashi mumkin)
private var cachesDirectory: URL {
FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
}
func saveImage(image: UIImage, fileName: String) throws {
guard let data = image.jpegData(compressionQuality: 0.8) else { return }
let url = documentsDirectory.appendingPathComponent(fileName)
try data.write(to: url, options: .atomic)
}
func loadImage(fileName: String) -> UIImage? {
let url = documentsDirectory.appendingPathComponent(fileName)
guard FileManager.default.fileExists(atPath: url.path) else { return nil }
return UIImage(contentsOfFile: url.path)
}
}
5. SwiftData (iOS 17+)
SwiftData — Apple'ning eng yangi deklarativ ORM tizimi bo'lib, Swift makrolariga asoslangan.
Model E'lon Qilish:
import SwiftData
@Model
final class TaskItem {
var id: UUID
var title: String
var isCompleted: Bool
var createdAt: Date
init(title: String, isCompleted: Bool = false) {
self.id = UUID()
self.title = title
self.isCompleted = isCompleted
self.createdAt = Date()
}
}
SwiftUI'da Ishlatish:
import SwiftUI
import SwiftData
struct TaskListView: View {
@Environment(\.modelContext) private var modelContext
// So'rov (Filter va Sort bilan)
@Query(filter: #Predicate<TaskItem> { !$0.isCompleted }, sort: \.createdAt, order: .reverse)
private var tasks: [TaskItem]
var body: some View {
List {
ForEach(tasks) { task in
Text(task.title)
}
.onDelete(perform: deleteTasks)
}
.toolbar {
Button("Qo'shish") {
let newTask = TaskItem(title: "Yangi vazifa")
modelContext.insert(newTask)
}
}
}
private func deleteTasks(at offsets: IndexSet) {
for index in offsets {
modelContext.delete(tasks[index])
}
}
}
6. Core Data (Klassik Stack)
import CoreData
final class CoreDataManager {
static let shared = CoreDataManager()
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "AppModel")
container.loadPersistentStores { _, error in
if let error = error {
fatalError("CoreData yuklanmadi: \(error)")
}
}
return container
}()
var context: NSManagedObjectContext {
persistentContainer.viewContext
}
// Saqlash
func save() {
if context.hasChanges {
do {
try context.save()
} catch {
print("Saqlashda xato:", error)
}
}
}
// Qidiruv (Fetch Request)
func fetchTasks() -> [TaskEntity] {
let request: NSFetchRequest<TaskEntity> = TaskEntity.fetchRequest()
request.predicate = NSPredicate(format: "isCompleted == NO")
request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
do {
return try context.fetch(request)
} catch {
return []
}
}
}