Published on

Firebase Firestore'da foydalanuvchi profilini yaratish (user profiles)

Authors

Auth va Firestore: Farqi nima?

Ko'pchilik yangi o'rganayotgan dasturchilar bitta narsada adashadi: Firebase Authentication bu faqatgina odamni tanib olish (autentifikatsiya) uchun xizmat qiladi. U yerdan biz faqatgina uid (User ID), email va xavfsizlik tokenlarini olamiz xolos. Ammo foydalanuvchining ilova ichidagi ma'lumotlari (masalan: Ismi nima? U qaysi davlatdan? Premium obunasi bormi?) kabi narsalarni u yerda saqlab bo'lmaydi. Bu ma'lumotlarni biz o'zimizning Firestore ma'lumotlar bazamizdagi "Foydalanuvchilar" (Users) kolleksiyasida saqlashimiz kerak.

Shuning uchun to'g'ri oqim (flow) har doim shunday bo'ladi:

  1. Foydalanuvchi ilovaga kiradi (Auth orqali).
  2. Tizim unga yangi o'zgarmas uid (User ID) beradi.
  3. Biz shu zahoti Firestore'ga kirib, users degan kolleksiya ochamiz va aynan o'sha uid nomli User Profile hujjatini yaratib qo'yamiz.
  4. Keyin ilovaning qolgan joylarida faqat o'sha Firestore'dagi hujjat ustida ishlaymiz.

1-qadam: Kutubxonalarni o'rnatish

Agar xotirangizda bo'lsa, loyiha boshida biz faqat FirebaseAuth paketini o'rnatgan edik. Endi bizga Firestore kerak.

  1. Xcode'da loyiha sozlamalaridan Package Dependencies bo'limiga kiring.
  2. Firebase paketini tanlang.
  3. Ro'yxatdan FirebaseFirestore va FirebaseFirestoreSwift (bu async/await va Codable uchun muhim) paketlarini belgilab loyihaga qo'shing.

2-qadam: UserManager klassi

Oldingi darslarda AuthenticationManager ochganimiz kabi, endi Firestore bilan ishlash uchun UserManager degan alohida menejer klassini yaratamiz:

import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift

final class UserManager {

    // Singleton (yagona nusxa) pattern
    static let shared = UserManager()
    private init() {}

    // Firestore'ga kirish uchun yo'l
    private let userCollection = Firestore.firestore().collection("users")
}

3-qadam: Hujjat yaratish (Write)

Endi yangi foydalanuvchi profilini yaratadigan funksiyani yozamiz. Biz ma'lumotlarni baza tushunadigan Dictionary [String: Any] shaklida beramiz. Bu yerda hujjat ID'si sifatida document() ichiga ataylab Firebase Auth bergan uid ni kiritamiz (avtomatik ID yaratilmasligi uchun):

func createNewUser(authData: AuthDataResultModel) async throws {
    // 1. Bazaga yozish uchun ma'lumotlarni tayyorlash
    var userData: [String: Any] = [
        "user_id": authData.uid,
        "is_anonymous": authData.isAnonymous,
        "date_created": Timestamp() // Firebase'ning maxsus sana formati
    ]

    if let email = authData.email {
        userData["email"] = email
    }

    // 2. Ma'lumotni bazaga jo'natish (setData)
    try await userCollection.document(authData.uid).setData(userData, merge: false)
}

Nega merge: false? Chunki biz yangi hujjat yaratyapmiz va uni noldan yozishimiz kerak. merge: true esa bor hujjatning ustiga faqat ma'lum joylarini yangilash (update) uchun ishlatiladi.

Endi buni AuthenticationManager dan foydalanuvchi ro'yxatdan o'tgan zahotiyoq chaqirib qo'yishni unutmang!

4-qadam: Hujjatni o'qib olish (Read)

Bazada profil paydo bo'ldi. Dasturni yopib qayta ochganda bu ma'lumotlarni qanday qilib Swift kodi ichiga qaytarib olamiz? Buning uchun avval Swift Data Modelini (Struct) tuzib olamiz:

struct DBUser {
    let userId: String
    let isAnonymous: Bool?
    let email: String?
    let dateCreated: Date?
}

Va UserManager ichiga getUser funksiyasini yozamiz. Unda .getDocument() orqali ma'lumotni tortib olib, har bir fieldni o'z qo'limiz bilan bittalab ajratib olamiz:

func getUser(userId: String) async throws -> DBUser {
    // 1. Hujjatni Snapshot ko'rinishida tortib olish
    let snapshot = try await userCollection.document(userId).getDocument()

    // 2. Snapshot ichidan Dictionary ma'lumotni olish
    guard let data = snapshot.data() else {
        throw URLError(.badServerResponse)
    }

    // 3. Dictionary'dan kerakli maydonlarni bittalab ajratib olish (Parsing)
    let uid = data["user_id"] as? String ?? ""
    let isAnonymous = data["is_anonymous"] as? Bool
    let email = data["email"] as? String

    // Timestamp'ni Swift Date'iga o'girish
    let dateCreated = (data["date_created"] as? Timestamp)?.dateValue()

    // 4. Swift obyektini qaytarish
    return DBUser(
        userId: uid,
        isAnonymous: isAnonymous,
        email: email,
        dateCreated: dateCreated
    )
}

Xulosa

Bizning kodimiz juda yaxshi ishlayapti, ammo tasavvur qiling, profilingizda 50 xil maydon (Ism, Yosh, Rasmlar array'i, Manzil va hokazo) bo'lsa... Ularni data["key"] as? Type shaklida bittalab yozib chiqish qanchalik mashaqqatli va xato qilish ehtimoli yuqori! Nastarin kelajak! Keyingi darsda biz Swift'ning ajoyib imkoniyati — Codable dan foydalanib, bu amallarni avtomatlashtirishni (qo'lda yozmaslikni) o'rganamiz. Bu sizning yuzlab qator kodingizni qisqartirib beradi!

Buy mea coffee