Firebase iOS कोडलैब: FriendlyChat

1. खास जानकारी

iOS के लिए FriendlyChat कोडलैब में आपका स्वागत है! इस कोडलैब में, आपको Firebase और Swift की आधुनिक सुविधाओं, जैसे कि SwiftUI, Swift Concurrency, और Observation फ़्रेमवर्क का इस्तेमाल करके, रीयल-टाइम में काम करने वाला iOS चैट ऐप्लिकेशन बनाने का तरीका सीखने को मिलेगा.

आपको क्या सीखने को मिलेगा

  • Observation फ़्रेमवर्क (@Observable) की मदद से, स्टेट मैनेज करना.
  • Firebase से पुष्टि करने की सुविधा का इस्तेमाल करके, उपयोगकर्ताओं की पुष्टि करना.
  • Cloud Firestore का इस्तेमाल करके, चैट मैसेज को रीयल टाइम में सिंक करना.
  • Firebase के लिए Cloud Storage का इस्तेमाल करके, इमेज सेव करना और उन्हें दिखाना.
  • Swift Concurrency की आधुनिक सुविधाओं का इस्तेमाल करके, Firebase के एपीआई ऐक्सेस करना.

आपको इनकी ज़रूरत होगी

  • Xcode का नया वर्शन
  • iOS सिम्युलेटर या टेस्ट के लिए कोई डिवाइस
  • Firebase प्रोजेक्ट बनाने और उसे मैनेज करने के लिए, Google खाता

2. सैंपल कोड पाना

कमांड लाइन से, GitHub के डेटा स्टोर करने की जगह का क्लोन बनाएं:

$ git clone https://github.com/firebase/codelab-friendlychat-ios

codelab-friendlychat-ios के डेटा स्टोर करने की जगह में, कई सैंपल प्रोजेक्ट शामिल हैं:

  • ios-starter/swift-starter — यह Xcode का शुरुआती प्रोजेक्ट है. इसमें SwiftUI लेआउट का ढांचा और TODO टिप्पणियां शामिल हैं. इनकी मदद से, Firebase के साथ ऐप्लिकेशन की सुविधाएं लागू की जा सकती हैं.
  • ios/swift — यह Xcode का पूरा प्रोजेक्ट है. इसमें सैंपल ऐप्लिकेशन भी शामिल है.

3. शुरुआती ऐप्लिकेशन बनाना

यूज़र इंटरफ़ेस के बारे में जानने के लिए, शुरुआती ऐप्लिकेशन बनाएं और उसे चलाएं:

  1. Finder या Terminal में, ios-starter/swift-starter डायरेक्ट्री पर जाएं.
  2. Xcode में प्रोजेक्ट खोलने के लिए, FriendlyChatSwift.xcodeproj पर दो बार क्लिक करें.
  3. ध्यान दें कि Xcode, बैकग्राउंड में Swift Package Manager की डिपेंडेंसी अपने-आप हल करता है. इसके लिए, वह GitHub से firebase-ios-sdk का 12वां या इसके बाद का वर्शन डाउनलोड करता है.
  4. कोई iOS सिम्युलेटर चुनें. जैसे, iPhone 17 Pro. इसके बाद, चलाएं बटन (cmd+R) पर क्लिक करें.

कुछ सेकंड बाद, FriendlyChat की लॉगिन स्क्रीन दिखेगी. इस समय, लॉगिन बटन और मैसेज फ़ीड, प्लेसहोल्डर के तौर पर दिखते हैं. अगले चरणों में, आपको Firebase को ऐप्लिकेशन से कनेक्ट करना होगा.

4. Firebase प्रोजेक्ट सेट अप करना

नया Firebase प्रोजेक्ट बनाना

  1. अपने Google खाते का इस्तेमाल करके, Firebase कंसोल में साइन इन करें.
  2. नया प्रोजेक्ट बनाने के लिए, बटन पर क्लिक करें. इसके बाद, प्रोजेक्ट का नाम डालें. जैसे, FriendlyChat.
  3. जारी रखें पर क्लिक करें.
  4. अगर आपसे पूछा जाए, तो Firebase की शर्तें देखें और उन्हें स्वीकार करें. इसके बाद, जारी रखें पर क्लिक करें.
  5. (ज़रूरी नहीं) Firebase कंसोल में, एआई की मदद से सहायता पाने की सुविधा चालू करें. इसे "Firebase में Gemini" कहा जाता है.
  6. इस कोडलैब के लिए, आपको Google Analytics की ज़रूरत नहीं है. इसलिए, Google Analytics के विकल्प को बंद करें.
  7. प्रोजेक्ट बनाएं पर क्लिक करें. इसके बाद, प्रोजेक्ट के लिए ज़रूरी संसाधन उपलब्ध होने का इंतज़ार करें. फिर जारी रखें पर क्लिक करें.

Firebase के लिए, कीमत चुकाने वाले प्लान पर अपग्रेड करना

Firebase के लिए Cloud Storage का इस्तेमाल करने के लिए, आपका Firebase प्रोजेक्ट, इस्तेमाल के हिसाब से पैसे चुकाने वाले (Blaze) प्लान पर होना चाहिए. इसका मतलब है कि यह Cloud Billing खाते से लिंक होना चाहिए.

  • Cloud Billing खाते के लिए, क्रेडिट कार्ड जैसी किसी पेमेंट मेथड की ज़रूरत होती है.
  • अगर आपने Firebase और Google Cloud का इस्तेमाल पहली बार किया है, तो देखें कि क्या आपके पास 300 डॉलर का क्रेडिट और मुफ़्त में आज़माने के लिए Cloud Billing खाता पाने की ज़रूरी शर्तें पूरी होती हैं.
  • अगर आप किसी इवेंट के हिस्से के तौर पर यह कोडलैब कर रहे हैं, तो अपने आयोजक से पूछें कि क्या Cloud क्रेडिट उपलब्ध हैं.

अपने प्रोजेक्ट को Blaze प्लान पर अपग्रेड करने के लिए, यह तरीका अपनाएं:

  1. Firebase कंसोल में, अपना प्लान अपग्रेड करने के लिए, चुनें.
  2. Blaze प्लान चुनें. अपने प्रोजेक्ट को Cloud Billing खाते से लिंक करने के लिए, स्क्रीन पर दिए गए निर्देशों का पालन करें.
    अगर आपको इस अपग्रेड के हिस्से के तौर पर, Cloud Billing खाता बनाना पड़ा है, तो अपग्रेड पूरा करने के लिए, आपको Firebase कंसोल में अपग्रेड फ़्लो पर वापस जाना पड़ सकता है.

अपने iOS ऐप्लिकेशन को कनेक्ट करना

  1. प्रोजेक्ट की खास जानकारी वाली स्क्रीन पर, ऐप्लिकेशन सेटअप करने का वर्कफ़्लो लॉन्च करने के लिए, iOS आइकॉन पर क्लिक करें.
  2. बंडल आईडी डालें:
    com.google.firebase.codelab.FriendlyChatSwift
    
  3. ऐप्लिकेशन रजिस्टर करें पर क्लिक करें.

अपने Xcode प्रोजेक्ट में GoogleService-Info.plist जोड़ना

  1. कॉन्फ़िगरेशन फ़ाइल सेव करने के लिए, GoogleService-Info.plist डाउनलोड करें पर क्लिक करें.
  2. Xcode में, डाउनलोड की गई GoogleService-Info.plist फ़ाइल को, प्रोजेक्ट नेविगेटर में मौजूद FriendlyChatSwift के मुख्य ग्रुप में खींचें और छोड़ें.
  3. प्रॉम्प्ट मिलने पर, पक्का करें कि ज़रूरत पड़ने पर आइटम कॉपी करें चेक किया गया हो और FriendlyChatSwift टारगेट चुना गया हो. इसके बाद, पूरा करें पर क्लिक करें.

FriendlyChatSwiftApp.swift में Firebase को कॉन्फ़िगर करना

आखिर में, SwiftUI ऐप्लिकेशन लॉन्च होने पर, Firebase को अपने प्रोजेक्ट के कॉन्फ़िगरेशन के साथ शुरू करें. FriendlyChatSwiftApp.swift खोलें और TODO प्लेसहोल्डर को import FirebaseCore और FirebaseApp.configure() से बदलें:

import SwiftUI
import FirebaseCore

@main
struct FriendlyChatSwiftApp: App {
  init() {
    FirebaseApp.configure()
  }

  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }
}

5. उपयोगकर्ताओं की पुष्टि करना

Firebase कंसोल में, पुष्टि करने की सुविधा को कॉन्फ़िगर करना

उपयोगकर्ताओं की पुष्टि करने से पहले, आपको Firebase कंसोल में अपनी पसंद के ऑथ प्रोवाइडर को चालू करना होगा. इस ट्यूटोरियल में, ईमेल/पासवर्ड से पुष्टि करने की सुविधा का इस्तेमाल किया गया है:

  1. Firebase कंसोल में, सुरक्षा > पुष्टि करने की सुविधा पर जाएं. इसके बाद, शुरू करें पर क्लिक करें.
  2. साइन-इन का तरीका टैब चुनें.
  3. ईमेल/पासवर्ड पर क्लिक करें. इसके बाद, चालू करें टॉगल स्विच पर क्लिक करें और सेव करें पर क्लिक करें.

पुष्टि करने के नियमों की मदद से, Cloud Firestore को सुरक्षित करना

इसके बाद, उपयोगकर्ताओं को मैसेज पढ़ने या लिखने से पहले, पुष्टि करने के लिए कहें:

  1. Firebase कंसोल में, डेटाबेस और स्टोरेज > Firestore डेटाबेस पर जाएं. इसके बाद, डेटाबेस बनाएं पर क्लिक करें.
  2. कोई जगह चुनें और आगे बढ़ें पर क्लिक करें.
  3. टेस्ट मोड में शुरू करें को चुनें और बनाएं पर क्लिक करें.
  4. नियम टैब चुनें और सुरक्षा के नियमों को इस तरह अपडेट करें:
    rules_version = '2';
    
    service cloud.firestore {
      match /databases/{database}/documents {
        match /messages/{messageId} {
          allow read, write: if request.auth != null;
        }
      }
    }
    
    इन नियमों के तहत, पुष्टि किया गया कोई भी उपयोगकर्ता, डेटाबेस में मैसेज पढ़ या लिख सकता है. यह सीखने के मकसद से सही है. सुरक्षा के नियमों के बारे में ज़्यादा जानने के लिए, सुरक्षा के नियमों से जुड़ा दस्तावेज़ पढ़ें.
  5. पब्लिश करें पर क्लिक करें.

UserViewModel.swift में, पुष्टि करने की सुविधा की स्थिति देखना

SwiftUI में, Firebase Auth की स्थिति को देखने से, यूज़र इंटरफ़ेस (यूआई) लॉगिन स्क्रीन और चैट इंटरफ़ेस के बीच आसानी से स्विच करता है.

ViewModels/UserViewModel.swift खोलें और init() में मौजूद TODO को, authStateChanges AsyncSequence का इस्तेमाल करके, पुष्टि करने की सुविधा की स्थिति में होने वाले बदलावों को देखने के लिए बदलें:

  init() {
    authTask = Task {
      for await user in Auth.auth().authStateChanges {
        self.user = user
      }
    }
  }

Swift Concurrency की मदद से, साइन-इन, साइन-अप, और साइन-आउट की सुविधा लागू करना

UserViewModel.swift में, बचे हुए TODO टिप्पणियों को, async/await के आधुनिक पुष्टि करने के तरीकों से बदलें:

  func signIn(email: String, password: String) async {
    errorMessage = nil
    if email.isEmpty || password.isEmpty {
      showError("Please enter both email and password.")
      return
    }
    do {
      try await Auth.auth().signIn(withEmail: email, password: password)
    } catch {
      showError(error.localizedDescription)
    }
  }

  func signUp(email: String, password: String, displayName: String) async {
    errorMessage = nil
    if email.isEmpty || password.isEmpty {
      showError("Please enter both email and password.")
      return
    }
    do {
      let result =
        try await Auth.auth().createUser(withEmail: email, password: password)
      let changeRequest = result.user.createProfileChangeRequest()
      changeRequest.displayName = displayName.isEmpty ? email : displayName
      try await changeRequest.commitChanges()
      self.user = Auth.auth().currentUser
    } catch {
      showError(error.localizedDescription)
    }
  }

  func updateDisplayName(_ displayName: String) async {
    guard let currentUser = Auth.auth().currentUser else { return }
    do {
      let changeRequest = currentUser.createProfileChangeRequest()
      changeRequest.displayName = displayName
      try await changeRequest.commitChanges()
      self.user = Auth.auth().currentUser
    } catch {
      showError(error.localizedDescription)
    }
  }

  func signOut() {
    do {
      try Auth.auth().signOut()
    } catch {
      showError(error.localizedDescription)
    }
  }

उपयोगकर्ता की पुष्टि करने की सुविधा की जांच करना

  1. Xcode में, चलाएं बटन पर क्लिक करें.
  2. ऐप्लिकेशन सिम्युलेटर में, साइन अप करें पर क्लिक करें. इसके बाद, डिसप्ले नेम, ईमेल, और पासवर्ड डालें. फिर साइन अप करें पर टैप करें.
  3. आपको अपने-आप पुष्टि हो जाएगी और आपको मैसेजिंग की खाली स्क्रीन पर ले जाया जाएगा!

6. Cloud Firestore से डेटा पढ़ना

Firebase कंसोल में, सैंपल मैसेज जोड़ना

डेटाबेस में सैंपल मैसेज जोड़ें:

  1. Firebase कंसोल में, Firestore डेटाबेस पर जाएं और डेटा टैब चुनें.
  2. कलेक्शन शुरू करें पर क्लिक करें.
  3. **कलेक्शन आईडी** के लिए, messages डालें. इसके बाद, **आगे बढ़ें** पर क्लिक करें.
  4. डॉक्यूमेंट आईडी को अपने-आप जनरेट होने के लिए सेट करें या ऑटो-आईडी पर क्लिक करें.
  5. डॉक्यूमेंट में ये फ़ील्ड जोड़ें:
    • text (टाइप: string, वैल्यू: Hello)
    • displayName (टाइप: string, वैल्यू: anonymous)
  6. सेव करें पर क्लिक करें.
  7. ज़्यादा सैंपल मैसेज जोड़ने के लिए, डॉक्यूमेंट जोड़ें पर क्लिक करें. यह ज़रूरी नहीं है.

FriendlyMessageViewModel.swift में मैसेज सिंक करना

SwiftUI में, @Observable मॉडल, डिक्लेरेटिव यूज़र इंटरफ़ेस (यूआई) अपडेट करता है. ViewModels/FriendlyMessageViewModel.swift खोलें और snapshots AsyncSequence का इस्तेमाल करके, startListening() और stopListening() लागू करें:

  func startListening() {
    stopListening()
    listenerTask = Task {
      let db = Firestore.firestore()
      do {
        for try await snapshot in db.collection("messages").snapshots {
          self.messages = snapshot.documents.compactMap { document in
            try? document.data(as: FriendlyMessage.self)
          }
        }
      } catch {
        print("Error listening for messages: \(error)")
      }
    }
  }

  func stopListening() {
    listenerTask?.cancel()
    listenerTask = nil
    messages.removeAll()
  }

SwiftUI, मैसेज को कैसे रेंडर करता है और अपने-आप स्क्रोल करता है

Views/ContentView.swift में, देखें कि ScrollViewReader और LazyVStack, चैट बबल को कैसे रेंडर करते हैं. साथ ही, messages.count में बदलाव होने पर, सबसे नए मैसेज पर अपने-आप स्क्रोल कैसे करते हैं:

ScrollViewReader { scrollViewReader in
  ScrollView {
    LazyVStack(spacing: 12) {
      ForEach(messageViewModel.messages) { message in
        FriendlyMessageView(friendlyMessage: message)
          .id(message.id)
      }
    }
    .padding(.horizontal)
    .onChange(of: messageViewModel.messages.count) { _, count in
      guard count > 0,
            let lastId = messageViewModel.messages.last?.id else { return }
      withAnimation(.easeInOut) {
        scrollViewReader.scrollTo(lastId, anchor: .bottom)
      }
    }
  }
}

डेटाबेस की स्थिति को सीधे व्यू मॉडल के ज़रिए यूज़र इंटरफ़ेस (यूआई) की स्थिति से जोड़कर, SwiftUI, ऐप्लिकेशन कोड को ट्रांज़िशन को ऐनिमेशन में साफ़ तौर पर मैप करने की अनुमति देता है. अगले चरण में, इस ऐनिमेशन को देखने के लिए, ऐप्लिकेशन से डेटाबेस में डेटा लिखा जाएगा.

7. मैसेज भेजना

Swift Concurrency की मदद से, sendMessage लागू करना

addDocument() का इस्तेमाल करके, किसी कलेक्शन में कोई दस्तावेज़ जोड़ने पर, Cloud Firestore हर चैट मैसेज के लिए एक यूनीक आईडी जनरेट करता है.

ViewModels/FriendlyMessageViewModel.swift में, TODO को, sendMessage(text:imageUrl:) में मौजूद async throws तरीके से बदलें:

  func sendMessage(text: String?, imageUrl: String?) async throws {
    guard let currentUser = Auth.auth().currentUser else { return }
    let message = FriendlyMessage(
      text: text,
      displayName: currentUser.displayName ?? currentUser.email ?? "Anonymous",
      imageUrl: imageUrl,
      userId: currentUser.uid
    )
    let db = Firestore.firestore()
    _ = try db.collection("messages").addDocument(from: message)
  }

मैसेज भेजने की सुविधा की जांच करना

  1. Xcode में, चलाएं बटन पर क्लिक करें.
  2. अपने खाते में साइन इन करें.
  3. सबसे नीचे मौजूद टेक्स्ट फ़ील्ड में कोई मैसेज टाइप करें और भेजें आइकॉन पर टैप करें.
  4. देखें कि मैसेज आपके सिम्युलेटर में तुरंत दिखता है या नहीं!

8. इमेज सेव करना और पाना

Firebase के लिए Cloud Storage सेट अप करना

  1. Firebase कंसोल में, डेटाबेस और स्टोरेज > स्टोरेज पर जाएं. इसके बाद, शुरू करें पर क्लिक करें.
  2. टेस्ट मोड में शुरू करें को चुनें और आगे बढ़ें पर क्लिक करें.
  3. स्टोरेज की डिफ़ॉल्ट जगह स्वीकार करें और हो गया पर क्लिक करें.

SwiftUI PhotosPicker की मदद से, नेटिव इमेज पिकिंग की सुविधा

SwiftUI (iOS 16 या इसके बाद के वर्शन) में, import PhotosUI से PhotosPicker के ज़रिए, फ़ोटो चुनने की नेटिव सुविधा मिलती है. इसके लिए, UIKit डेलिगेट ब्रिज या UIImagePickerController रैपर की ज़रूरत नहीं होती!

Views/FooterView.swift में, देखें कि PhotosPicker, चुनी गई इमेज को कैसे बाइंड करता है:

PhotosPicker(selection: $selectedItem, matching: .images) {
  Image(systemName: "photo.on.rectangle.angled")
    .font(.system(size: 26))
    .foregroundStyle(.blue)
    .accessibilityLabel("Select photo")
}
.onChange(of: selectedItem) { _, newItem in
  Task {
    if let data = try? await newItem?.loadTransferable(type: Data.self) {
      await uploadAndSendImage(data: data)
    }
  }
}

इमेज अपलोड करने की सुविधा लागू करना

कोई फ़ोटो चुनने पर, इमेज डेटा को Cloud Storage पर अपलोड करें और सार्वजनिक तौर पर डाउनलोड करने का यूआरएल, Cloud Firestore में सेव करें.

Views/FooterView.swift में, TODO में मौजूद uploadAndSendImage(data:) को बदलें:

  private func uploadAndSendImage(data: Data) async {
    guard let uid = Auth.auth().currentUser?.uid else { return }
    isUploading = true
    defer {
      isUploading = false
      selectedItem = nil
    }
    do {
      let filename = "\(uid)/\(UUID().uuidString).jpg"
      let storageRef =
        Storage.storage().reference().child("images").child(filename)
      let metadata = StorageMetadata()
      metadata.contentType = "image/jpeg"

      _ = try await storageRef.putDataAsync(data, metadata: metadata)
      let downloadURL = try await storageRef.downloadURL()
      try await viewModel.sendMessage(
        text: nil, imageUrl: downloadURL.absoluteString)
    } catch {
      print("Error uploading image: \(error.localizedDescription)")
    }
  }

Cloud Storage की मदद से इमेज शेयर करना

Views/FriendlyMessageImageView.swift में, इमेज के यूआरएल को Swift Concurrency और Cloud Storage SDK का इस्तेमाल करके, एसिंक्रोनस तरीके से लोड किया जाता है:

  • स्टैंडर्ड एचटीटीपी/एचटीटीपीएस डाउनलोड यूआरएल, URLSession के ज़रिए एसिंक्रोनस तरीके से वापस पाए जाते हैं.
  • Google Cloud Storage के यूआरएल (उदाहरण के लिए, gs://...) को Storage.storage().reference(forURL:) का इस्तेमाल करके फ़ेच किया जाता है.

इमेज वाले मैसेज की जांच करना

  1. Xcode में, चलाएं बटन पर क्लिक करें.
  2. अपने खाते में साइन इन करें.
  3. फ़ोटो आइकॉन पर टैप करें. इसके बाद, लाइब्रेरी से कोई इमेज चुनें. देखें कि वह अपलोड होती है या नहीं और चैट में दिखती है या नहीं!

9. नतीजा

बधाई हो, आपने Swift और Firebase का इस्तेमाल करके, रीयल-टाइम में काम करने वाला iOS चैट ऐप्लिकेशन बना लिया है!

आपने ये सब सीखा

  • firebase-ios-sdk के लिए, Swift Package Manager (SPM) को Xcode में इंटिग्रेट करना.
  • SwiftUI के डिक्लेरेटिव लेआउट, PhotosPicker, और ScrollViewReader की मदद से, अपने-आप स्क्रोल करने की सुविधा.
  • पुष्टि करने की सुविधा, Cloud Firestore, और Cloud Storage के लिए, Swift Concurrency (async/await).
  • ईमेल/पासवर्ड और गुमनाम तरीके से पुष्टि करने की सुविधा के साथ, रिएक्टिव स्टेट ऑब्ज़र्वेशन.
  • Cloud Firestore में, रीयल-टाइम स्नैपशॉट सुनने की सुविधा और आईडी अपने-आप लिखने की सुविधा.
  • Firebase के लिए Cloud Storage में, बाइनरी अपलोड और सार्वजनिक तौर पर डाउनलोड करने के यूआरएल.

ज़्यादा जानें