Firebase iOS Codelab'i: FriendlyChat

1. Genel Bakış

iOS için FriendlyChat codelab'ine hoş geldiniz. Bu codelab'de, Firebase'i ve SwiftUI, Swift Concurrency ve Observation Framework gibi modern Swift özelliklerini kullanarak tam özellikli bir gerçek zamanlı sohbet iOS uygulaması oluşturmayı öğreneceksiniz.

Neler öğreneceksiniz?

  • Durumu modern Observation framework (@Observable) ile yönetin.
  • Firebase Authentication'ı kullanarak kullanıcıların kimliğini doğrulayın.
  • Cloud Firestore'u kullanarak sohbet mesajlarını anında senkronize edin.
  • Cloud Storage for Firebase'i kullanarak resimleri depolama ve yayınlama.
  • Modern Swift Concurrency özelliklerini kullanarak Firebase API'lerine erişin.

Gerekenler

  • Xcode'un en son sürümü
  • iOS simülatörü veya fiziksel test cihazı
  • Firebase projenizi oluşturup yönetmek için bir Google Hesabı

2. Örnek kodu alın

GitHub deposunu komut satırından klonlayın:

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

codelab-friendlychat-ios deposunda çeşitli örnek projeler bulunur:

  • ios-starter/swift-starter: SwiftUI düzeni iskeletini ve Firebase ile uygulama özelliklerini uygulayacağınız TODO yorumlarını içeren başlangıç Xcode projesi.
  • ios/swift: Tamamlanmış örnek uygulamayı içeren, tamamlanmış Xcode projesi.

3. Başlangıç uygulamasını oluşturma

Kullanıcı arayüzüne alışmak için başlangıç uygulamasını oluşturup çalıştırın:

  1. Finder veya Terminal'de ios-starter/swift-starter dizinine gidin.
  2. Projeyi Xcode'da açmak için FriendlyChatSwift.xcodeproj simgesini çift tıklayın.
  3. Xcode'un, Swift Package Manager bağımlılarını arka planda otomatik olarak çözümlediğini (GitHub'dan firebase-ios-sdk v12+ sürümünü indirme) unutmayın.
  4. Bir iOS simülatörü (örneğin, iPhone 17 Pro) seçin ve Çalıştır düğmesini (cmd+R) tıklayın.

Birkaç saniye sonra FriendlyChat giriş ekranı görünür. Bu noktada, giriş düğmeleri ve ileti feed'leri yer tutucudur. Firebase'i uygulamaya bağlamak için aşağıdaki adımları uygulayın.

4. Firebase projesi oluşturma

Yeni bir Firebase projesi oluşturma

  1. Google Hesabınızı kullanarak Firebase konsolunda oturum açın.
  2. Yeni bir proje oluşturmak için düğmeyi tıklayın ve ardından bir proje adı girin (örneğin, FriendlyChat).
  3. Devam'ı tıklayın.
  4. İstenirse Firebase şartlarını inceleyip kabul edin ve Devam'ı tıklayın.
  5. (İsteğe bağlı) Firebase konsolunda yapay zeka yardımını etkinleştirin ("Firebase'de Gemini" olarak adlandırılır).
  6. Bu codelab için Google Analytics'e ihtiyacınız yoktur. Bu nedenle, Google Analytics seçeneğini devre dışı bırakın.
  7. Proje oluştur'u tıklayın, projenizin hazırlanmasını bekleyin ve ardından Devam'ı tıklayın.

Firebase fiyatlandırma planınızı yükseltme

Firebase için Cloud Storage'ı kullanmak istiyorsanız Firebase projenizin kullandıkça öde (Blaze) fiyatlandırma planında olması gerekir. Bu da projenin bir Cloud Faturalandırma hesabı'na bağlı olduğu anlamına gelir.

Projenizi Blaze planına geçirmek için aşağıdaki adımları uygulayın:

  1. Firebase konsolunda planınızı yükseltmeyi seçin.
  2. Blaze planını seçin. Bir Cloud Faturalandırma hesabını projenize bağlamak için ekrandaki talimatları uygulayın.
    Bu yükseltme kapsamında bir Cloud Faturalandırma hesabı oluşturmanız gerekiyorsa yükseltmeyi tamamlamak için Firebase Console'daki yükseltme akışına geri dönmeniz gerekebilir.

iOS uygulamanızı bağlama

  1. Uygulama kurulumu iş akışını başlatmak için Projeye Genel Bakış ekranında iOS simgesini tıklayın.
  2. Paket kimliğini girin:
    com.google.firebase.codelab.FriendlyChatSwift
    
  3. Uygulamayı kaydet'i tıklayın.

Xcode projenize GoogleService-Info.plist ekleme

  1. Yapılandırma dosyasını kaydetmek için Download GoogleService-Info.plist'i (GoogleService-Info.plist'i İndir) tıklayın.
  2. Xcode'da indirilen GoogleService-Info.plist dosyasını Proje Gezgini'ndeki FriendlyChatSwift ana grubuna sürükleyin.
  3. İstendiğinde Gerekirse öğeleri kopyala seçeneğinin işaretli olduğundan ve FriendlyChatSwift hedefinin seçildiğinden emin olun, ardından Bitir'i tıklayın.

Firebase'i FriendlyChatSwiftApp.swift içinde yapılandırma

Son olarak, SwiftUI uygulamanız başlatıldığında Firebase'i proje yapılandırmanızla başlatın. FriendlyChatSwiftApp.swift dosyasını açın ve TODO yer tutucularını import FirebaseCore ve FirebaseApp.configure() ile değiştirin:

import SwiftUI
import FirebaseCore

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

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

5. Kullanıcıların kimliklerini doğrulama

Firebase konsolunda kimlik doğrulamayı yapılandırma

Kullanıcıların kimliğini doğrulayabilmeniz için önce Firebase konsolunda tercih ettiğiniz kimlik doğrulama sağlayıcısını etkinleştirmeniz gerekir. Bu eğitimde e-posta/şifre kimlik doğrulaması kullanılır:

  1. Firebase konsolunda Güvenlik > Kimlik Doğrulama'ya gidin ve Başlayın'ı tıklayın.
  2. Oturum açma yöntemi sekmesini seçin.
  3. E-posta/Şifre'yi, Etkinleştir açma/kapatma düğmesini ve Kaydet'i tıklayın.

Kimlik doğrulama kurallarıyla Cloud Firestore'un güvenliğini sağlama

Ardından, kullanıcıların mesajları okumadan veya yazmadan önce kimliklerinin doğrulanmasını zorunlu kılın:

  1. Firebase konsolunda Veritabanları ve Depolama > Firestore Veritabanı'na gidin ve Veritabanı oluştur'u tıklayın.
  2. Bir konum seçip Sonraki'yi tıklayın.
  3. Test modunda başlat'ı seçin ve Oluştur'u tıklayın.
  4. Kurallar sekmesini seçin ve güvenlik kurallarını aşağıdaki şekilde güncelleyin:
    rules_version = '2';
    
    service cloud.firestore {
      match /databases/{database}/documents {
        match /messages/{messageId} {
          allow read, write: if request.auth != null;
        }
      }
    }
    
    Bu kurallar, kimliği doğrulanmış tüm kullanıcıların veritabanındaki iletileri okumasına veya yazmasına izin verir. Bu, öğrenme amaçları için uygundur. Güvenlik kuralları dokümanlarından güvenlik kuralları hakkında daha fazla bilgi edinin.
  5. Yayınla'yı tıklayın.

UserViewModel.swift'daki kimlik doğrulama durumunu gözlemleyin.

SwiftUI'da Firebase Auth durumunu reaktif olarak gözlemlemek, kullanıcı arayüzünüzün oturum açma ekranı ile sohbet arayüzü arasında sorunsuz bir şekilde geçiş yapmasını sağlar.

ViewModels/UserViewModel.swift dosyasını açın ve authStateChanges AsyncSequence kullanarak kimlik doğrulama durumu değişikliklerini gözlemlemek için init() içindeki TODO öğesini değiştirin:

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

Swift Concurrency ile oturum açma, kaydolma ve oturumu kapatma işlemlerini uygulama

UserViewModel.swift içinde kalan TODO yorumlarını modern async/await kimlik doğrulama yöntemleriyle değiştirin:

  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)
    }
  }

Kullanıcı kimlik doğrulamasını test etme

  1. Xcode'da Çalıştır düğmesini tıklayın.
  2. Uygulama simülatöründe Sign Up'ı (Kaydol) tıklayın, Görünen Ad, E-posta ve Şifre girip SIGN UP'a (KAYDOL) dokunun.
  3. Otomatik olarak kimliğiniz doğrulanır ve boş mesajlaşma ekranına yönlendirilirsiniz.

6. Cloud Firestore'dan okuma

Firebase konsolunda örnek mesajlar ekleme

Veritabanını örnek mesajlarla doldurun:

  1. Firebase konsolunda Firestore Database'e gidin ve Data (Veri) sekmesini seçin.
  2. Koleksiyonu başlat'ı tıklayın.
  3. Collection ID (Koleksiyon Kimliği) için messages girin ve Next'i (Sonraki) tıklayın.
  4. Belge kimliği'nin otomatik olarak oluşturulmasını sağlayın (veya Otomatik kimlik'i tıklayın).
  5. Dokümana aşağıdaki alanları ekleyin:
    • text (tür: string, değer: Hello)
    • displayName (tür: string, değer: anonymous)
  6. Kaydet'i tıklayın.
  7. İsteğe bağlı olarak, daha fazla örnek mesaj eklemek için Belge ekle'yi tıklayın.

FriendlyMessageViewModel.swift uygulamasında iletileri senkronize etme

SwiftUI'da @Observable modeli, bildirimsel kullanıcı arayüzü güncellemelerini yönlendirir. ViewModels/FriendlyMessageViewModel.swift uygulamasını açın ve snapshots AsyncSequence kullanarak startListening() ile stopListening()'yi uygulayın:

  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'ın mesajları oluşturma ve otomatik kaydırma şekli

Views/ContentView.swift bölümünde, ScrollViewReader ve LazyVStack öğelerinin sohbet balonlarını nasıl oluşturduğunu ve messages.count her değiştiğinde en yeni mesaja otomatik olarak nasıl kaydırdığını inceleyin:

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, görünüm modeli aracılığıyla veritabanı durumunu doğrudan kullanıcı arayüzü durumuna bağlayarak uygulama kodunun geçişleri animasyonlarla temiz bir şekilde eşlemesine olanak tanır. Bir sonraki adımda, bu animasyonu uygulamada gözlemlemek için uygulamadan veritabanına veri yazacaksınız.

7. Mesaj gönderin

Swift Concurrency ile sendMessage'ı uygulama

addDocument() kullanarak bir koleksiyona belge eklediğinizde Cloud Firestore, her sohbet mesajı için benzersiz bir kimlik oluşturur.

ViewModels/FriendlyMessageViewModel.swift içinde, sendMessage(text:imageUrl:) içindeki TODO yerine bir async throws yöntemi koyun:

  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)
  }

Mesaj göndermeyi test etme

  1. Xcode'da Çalıştır düğmesini tıklayın.
  2. Hesabınızda oturum açın.
  3. Alt metin alanına bir mesaj yazıp Gönder simgesine dokunun.
  4. Mesajın simülatörünüzde anında görünmesini izleyin.

8. Resimleri depolama ve alma

Cloud Storage for Firebase'i ayarlama

  1. Firebase konsolunda Veritabanları ve Depolama > Depolama'ya gidin ve Başlayın'ı tıklayın.
  2. Test modunda başlat'ı seçin ve Sonraki'yi tıklayın.
  3. Varsayılan depolama konumunu kabul edin ve Bitti'yi tıklayın.

SwiftUI ile yerel resim seçme PhotosPicker

Modern SwiftUI (iOS 16+), import PhotosUI üzerinden PhotosPicker ile yerel fotoğraf seçimi sağlar. UIKit temsilci köprüleri veya UIImagePickerController sarmalayıcılar gerekmez.

Views/FooterView.swift bölümünde, PhotosPicker'nin seçilen resimleri nasıl bağladığını inceleyin:

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)
    }
  }
}

Resim yükleme özelliğini uygulama

Bir fotoğraf seçildiğinde, resim verilerini Cloud Storage'a yükleyin ve herkese açık indirme URL'sini Cloud Firestore'a kaydedin.

Views/FooterView.swift içinde, uploadAndSendImage(data:) bölümündeki TODO yerine şunu yazın:

  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 ile resim paylaşma

Views/FriendlyMessageImageView.swift içinde, resim URL'leri Swift Concurrency ve Cloud Storage SDK kullanılarak eşzamansız olarak yüklenir:

  • Standart HTTP/HTTPS indirme URL'leri, URLSession aracılığıyla eşzamansız olarak alınır.
  • Google Cloud Storage URL'leri (örneğin, gs://...), Storage.storage().reference(forURL:) kullanılarak getirilir.

Test resim mesajları

  1. Xcode'da Çalıştır düğmesini tıklayın.
  2. Hesabınızda oturum açın.
  3. Fotoğraf simgesine dokunun, kitaplıktan bir resim seçin ve resmin yüklenip sohbette görünmesini bekleyin.

9. Sonuç

Tebrikler, Swift ve Firebase kullanarak gerçek zamanlı bir iOS sohbet uygulaması geliştirdiniz.

Öğrendikleriniz

  • Swift Package Manager (SPM), firebase-ios-sdk için Xcode entegrasyonu.
  • SwiftUI ile bildirimli düzenler, PhotosPicker ve ScrollViewReader otomatik kaydırma.
  • Kimlik doğrulama, Cloud Firestore ve Cloud Storage'da Swift Concurrency (async/await)
  • Reaktif durum gözlemiyle E-posta/Şifre ve Anonim Kimlik Doğrulama.
  • Cloud Firestore gerçek zamanlı anlık görüntü dinleme ve otomatik kimlik yazma işlemleri.
  • Cloud Storage for Firebase ikili yüklemeleri ve herkese açık indirme URL'leri.

Daha fazla bilgi