- Published on
Firestore va Swift codable: ma'lumotlarni o'qish va yozishni avtomatlashtirish
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Nima muammo bor edi?
Oldingi darsda biz getUser funksiyasi ichida har bir maydonni qanday o'qib olganimizni eslang:
let uid = data["user_id"] as? String ?? ""
let isAnonymous = data["is_anonymous"] as? Bool
Agar DBUser ichida 30 ta maydon bo'lsa, bu degani siz yana 30 qator zerikarli kod yozishingiz, har gal xato qilish ehtimoli bilan to'qnashishingiz kerak degani. Swift tili ayni shunday takroriy va zerikarli vazifalarni hal qilish uchun Codable protokolini taqdim etgan.
Firebase SDK o'z navbatida ushbu protokolni to'liq qo'llab-quvvatlaydi!
1. Data modelni codable qilish
Buning uchun shunchaki avvalgi DBUser structimizga Codable yozuvini qo'shamiz:
struct DBUser: Codable {
let userId: String
let isAnonymous: Bool?
let email: String?
let dateCreated: Date?
var isPremium: Bool? // Yangi qo'shilgan maydon
}
Diqqat qiling, bu yerda biz Swift an'analariga ko'ra camelCase ishlatyapmiz (masalan, dateCreated). Lekin bazaga snake_case (masalan, date_created) bo'lib tushishi kerak.
2. Encoder va Decoder sozlash
Ushbu nomlar tarjimasini bajarish uchun UserManager klassimizda ikkita maxsus o'zgaruvchi yaratamiz:
final class UserManager {
static let shared = UserManager()
private init() {}
private let userCollection = Firestore.firestore().collection("users")
// Ma'lumotni yozishda (Encode) ishlatiladi
private let encoder: Firestore.Encoder = {
let encoder = Firestore.Encoder()
encoder.keyEncodingStrategy = .convertToSnakeCase // camelCase -> snake_case
return encoder
}()
// Ma'lumotni o'qishda (Decode) ishlatiladi
private let decoder: Firestore.Decoder = {
let decoder = Firestore.Decoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase // snake_case -> camelCase
return decoder
}()
}
Ushbu sozlamalar yordamida endi Swift va Firestore o'rtasidagi nomlash muammosi (konflikti) butunlay yo'qoladi!
3. Kodni qisqartirish (Refactoring)
Endi UserManager ichidagi eski funksiyalarimizni sehrli Codable bilan almashtiramiz.
Yozish (Create user)
Avvalgi 15 qatorli Dictionary yasash kodining o'rniga, endi shunchaki obyektdan bazaga yozib qo'yamiz:
func createNewUser(user: DBUser) async throws {
// setData(from:) funksiyasi obyektni avtomatik parchalaydi
try await userCollection.document(user.userId).setData(from: user, merge: false, encoder: encoder)
}
O'qish (Get user)
Barcha 20+ qatorli parchalash (parsing) kodlarini bitta qatorga almashtiramiz:
func getUser(userId: String) async throws -> DBUser {
// getDocument(as:) yordamida to'g'ridan-to'g'ri Swift obyekti olinadi
return try await userCollection.document(userId).getDocument(as: DBUser.self, decoder: decoder)
}
4. Faqat bitta maydonni yangilash (Update Data)
Yana bir juda muhim holat. Aytaylik, foydalanuvchi "Premium" sotib oldi va uning isPremium maydonini true ga o'zgartirishimiz kerak. Biz bunday holatda butun DBUser obyektini qaytadan bazaga jo'natishimiz (ya'ni setData qilishimiz) XATO hisoblanadi. Chunki bu vaqtda bizdagi qolgan ma'lumotlar eski bo'lib qolgan bo'lishi mumkin va bazadagi boshqa yangi narsalarni eskisiga almashtirib yuborishimiz mumkin.
Shuning uchun bunday kichik o'zgarishlarga har doim updateData ishlatiladi:
func updateUserPremiumStatus(userId: String, isPremium: Bool) async throws {
let data: [String: Any] = [
"is_premium": isPremium // Bu yerda nomni qo'lda berish kerak, chunki updateData Codable'ni tushunmaydi
]
// document mavjud bo'lsagina ishlaydi va FAQAT is_premium maydonini yangilaydi
try await userCollection.document(userId).updateData(data)
}
CAUTION
Esda saqlang:
- Yangi hujjat noldan yaratish uchun:
setData - Mavjud hujjatning barcha ma'lumotlarini to'liq o'zgartirish uchun:
setData(merge: false) - Hujjatdagi faqat bitta yoki bir nechta qatorni yangilash uchun:
updateDataishlatiladi.
Xulosa
Ushbu darsda yozgan kodimiz har qanday professional va katta hajmdagi ilovalarda qo'llaniladigan to'liq "Best Practice" hisoblanadi. Codable o'qish, kod hajmini qisqartirish, tip xavfsizligini ta'minlash (Type-safety) va Firebase bilan integratsiyada tengsiz vositadir.
Keyingi darslarda ushbu "Firebase Codable" imkoniyatlaridan kengroq foydalanib, murakkab Array va Map (dictionary) ma'lumot turlari ustida amallar bajarishni o'rganamiz!