Skip to content

Instantly share code, notes, and snippets.

@yimajo
Last active March 13, 2023 09:21
Show Gist options
  • Save yimajo/48495479a1d11417423b6f2dfbed85b1 to your computer and use it in GitHub Desktop.
Save yimajo/48495479a1d11417423b6f2dfbed85b1 to your computer and use it in GitHub Desktop.
An example of using TCA FirestoreClient with Firestore ios sdk automatically bridged from Objective-C to Swift Concurrency.
import Foundation
import ComposableArchitecture
import FirebaseFirestore
import FirebaseFirestoreSwift
// MARK: - FirestoreClient
struct FirestoreClient {
enum Input {
enum Create {
struct Food {
typealias ID = String
let name: String
let bestBeforeDate: Date
let userID: ID
}
}
}
var createFood: (Input.Create.Food, CollectionReference) async throws -> FirestoreEntity.FoodID
}
extension FirestoreClient {
static let liveValue = Self.live()
static func live() -> Self {
let firestore = Firestore.firestore()
let foodStorageCollectionName = "/foodStorages"
return Self(
createFood: { food, collectionReference in
// Objective-C completion handlers are automatically converted to async functions.
// https://github.com/apple/swift-evolution/blob/main/proposals/0297-concurrency-objc.md
let reference = try await collectionReference.addDocument(
data: try Firestore.Encoder().encode(
FirestoreEntity.Food(
name: food.name,
bestBeforeDate: food.bestBeforeDate
)
)
)
return reference.documentID
}
)
}
}
// MARK: - For SwiftUI Preview
extension FirestoreClient {
public static let noop = Self(
createFood: { _, _ in try await Task.never()}
)
}
// MARK: - For Dependencies
enum FirestoreClientKey: DependencyKey {
static let liveValue = FirestoreClient.liveValue
static let previewValue = FirestoreClient.noop
}
extension DependencyValues {
var firestoreClient: FirestoreClient {
get { self[FirestoreClientKey.self] }
set { self[FirestoreClientKey.self] = newValue }
}
}
// MARK: - FirestoreEntity
enum FirestoreEntity {}
extension FirestoreEntity {
typealias FoodID = String
struct Food: Equatable, Encodable, Decodable, Identifiable {
@DocumentID var id: FoodID?
@ServerTimestamp var createdDate: Timestamp?
let name: String
let bestBeforeDate: Date
}
}
extension FirestoreEntity.Food {
init(name: String, date: Date) {
self.name = name
self.bestBeforeDate = date
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment