Firebase Cloud Firestore support library for iOS. 🧢

Overview

🧢 Ballcap-iOS

Version Platform Downloads

Ballcap is a database schema design framework for Cloud Firestore.

Why Ballcap

Cloud Firestore is a great schema-less and flexible database that can handle data. However, its flexibility can create many bugs in development. Ballcap can assign schemas to Cloud Firestore to visualize data structures. This plays a very important role when developing as a team.

Inspired by https://github.com/firebase/firebase-ios-sdk/tree/pb-codable3

Please donate to continue development.

Sameple projects

Feature

☑️ Firestore's document schema with Swift Codable
☑️ Of course type safety.
☑️ It seamlessly works with Firestore and Storage.

Requirements ❗️

Installation

CocoaPods

  • Insert pod 'Ballcap' to your Podfile.
  • Run pod install.

If you have a Feature Request, please post an issue.

Usage

Document scheme

You must conform to the Codable and Modelable protocols to define Scheme.

struct Model: Codable, Equatable, Modelable {
    var number: Int = 0
    var string: String = "Ballcap"
}

Initialization

The document is initialized as follows:

// use auto id
let document: Document<Model> = Document()

print(document.data?.number) // 0
print(document.data?.string) // "Ballcap"

// KeyPath
print(document[\.number]) // 0
print(document[\.string]) // "Ballcap"


// Use your specified ID
let document: Document<Model> = Document(id: "YOUR_ID")

print(document.data?.number) // 0
print(document.data?.string) // "Ballcap"

// KeyPath
print(document[\.number]) // 0
print(document[\.string]) // "Ballcap"


// Use your specified DocumentReference
let documentReference: DocumentReference = Firestore.firestore().document("collection/document")
// note: If DocumentReference is specified, data is initialized with nil. 
let document: Document<Model> = Document(documentReference) 

print(document.data?.number) // nil
print(document.data?.string) // nil

// KeyPath
print(document[\.number]) // fail
print(document[\.string]) // fail

CRUD

Ballcap has a cache internally.When using the cache, use Batch instead of WriteBatch.

// save
document.save()

// update
document.update()

// delete
document.delete()

// Batch
let batch: Batch = Batch()
batch.save(document: document)
batch.update(document: document)
batch.delete(document: document)
batch.commit()

You can get data by using the get function.

Document<Model>.get(id: "DOCUMENT_ID", completion: { (document, error) in
    print(document.data)
})

The next get function gets data in favor of the cache. If there is no cached data, it gets from the server.

let document: Document<Model> = Document("DOCUMENT_ID")
document.get { (document, error) in
   print(document.data)
}

Why data is optional?

In CloudFirestore, DocumentReference does not necessarily have data. There are cases where there is no data under the following conditions.

  1. If no data is stored in DocumentReference.
  2. If data was acquired using Source.cache from DocumentReference, but there is no data in cache.

Ballcap recommends that developers unwrap if they can determine that there is data.

It is also possible to access the cache without using the network.

let document: Document<Model> = Document(id: "DOCUMENT_ID")
print(document.cache?.number) // 0
print(document.cache?.string) // "Ballcap"

Custom properties

Ballcap is preparing custom property to correspond to FieldValue.

ServerTimestamp

Property for handling FieldValue.serverTimestamp()

struct Model: Codable, Equatable {
    let serverValue: ServerTimestamp
    let localValue: ServerTimestamp
}
let model = Model(serverValue: .pending,
                  localValue: .resolved(Timestamp(seconds: 0, nanoseconds: 0)))

IncrementableInt & IncrementableDouble

Property for handling FieldValue.increment()

struct Model: Codable, Equatable, Modelable {
    var num: IncrementableInt = 0
}
let document: Document<Model> = Document()
document.data?.num = .increment(1)

OperableArray

Property for handling FieldValue.arrayRemove(), FieldValue.arrayUnion()

struct Model: Codable, Equatable, Modelable {
    var array: OperableArray<Int> = [0, 0]
}
let document: Document<Model> = Document()
document.data?.array = .arrayUnion([1])
document.data?.array = .arrayRemove([1])

File

File is a class for accessing Firestorage. You can save Data in the same path as Document by the follow:

let document: Document<Model> = Document(id: "DOCUMENT_ID")
let file: File = File(document.storageReference)

File supports multiple MIMETypes. Although File infers MIMEType from the name, it is better to input MIMEType explicitly.

  • plain
  • csv
  • html
  • css
  • javascript
  • octetStream(String?)
  • pdf
  • zip
  • tar
  • lzh
  • jpeg
  • pjpeg
  • png
  • gif
  • mp4
  • custom(String, String)

Upload & Download

Upload and Download each return a task. You can manage your progress by accessing tasks.

// upload
let ref: StorageReference = Storage.storage().reference().child("/a")
let data: Data = "test".data(using: .utf8)!
let file: File = File(ref, data: data, name: "n", mimeType: .plain)
let task = file.save { (metadata, error) in
    
}

// download
let task = file.getData(completion: { (data, error) in
    let text: String = String(data: data!, encoding: .utf8)!
})

StorageBatch

StorageBatch is used when uploading multiple files to Cloud Storage.

let textData: Data = "test".data(using: .utf8)!
let textFile: File = File(Storage.storage().reference(withPath: "c"), data: textData, mimeType: .plain)
batch.save(textFile)

let jpgData: Data = image.jpegData(compressionQuality: 1)!
let jpgFile: File = File(Storage.storage().reference(withPath: "d"), jpgData: textData, mimeType: .jpeg)
batch.save(jpgFile)
batch.commit { error in

}

DataSource

Ballcap provides a DataSource for easy handling of Collections and SubCollections.

DataSource initialize

from Document

let dataSource: DataSource<Item> = Document<Item>.query.dataSource()

from Collection Reference

CollectionReference

let query: DataSource<Document<Item>>.Query = DataSource.Query(Firestore.firestore().collection("items"))
let dataSource = DataSource(reference: query)

CollectionGroup

let query: DataSource<Document<Item>>.Query = DataSource.Query(Firestore.firestore().collectionGroup("items"))
let dataSource = DataSource(reference: query)

Your custom object

// from Custom class
let dataSource: DataSource<Item> = Item.query.dataSource()

// from CollectionReference
let query: DataSource<Item>.Query = DataSource.Query(Item.collectionReference)
let dataSource: DataSource<Item> = query.dataSource()

NSDiffableDataSourceSnapshot

self.dataSource = Document<Item>.query
    .order(by: "updatedAt", descending: true)
    .limit(to: 3)
    .dataSource()
    .retrieve(from: { (snapshot, documentSnapshot, done) in
        let document: Document<Item> = Document(documentSnapshot.reference)
        document.get { (item, error) in
            done(item!)
        }
    })
    .onChanged({ (snapshot, dataSourceSnapshot) in
        var snapshot: NSDiffableDataSourceSnapshot<Section, DocumentProxy<Item>> = self.tableViewDataSource.snapshot()
        snapshot.appendItems(dataSourceSnapshot.changes.insertions.map { DocumentProxy(document: $0)})
        snapshot.deleteItems(dataSourceSnapshot.changes.deletions.map { DocumentProxy(document: $0)})
        snapshot.reloadItems(dataSourceSnapshot.changes.modifications.map { DocumentProxy(document: $0)})
        self.tableViewDataSource.apply(snapshot, animatingDifferences: true)
    })
    .listen()

UITableViewDelegate, UITableViewDataSource

self.dataSource = Document<Item>.query
    .order(by: "updatedAt", descending: true)
    .limit(to: 3)
    .dataSource()
    .retrieve(from: { (snapshot, documentSnapshot, done) in
        let document: Document<Item> = Document(documentSnapshot.reference)
        document.get { (item, error) in
            done(item!)
        }
    })
    .onChanged({ (snapshot, dataSourceSnapshot) in
        self.tableView.performBatchUpdates({
            self.tableView.insertRows(at: dataSourceSnapshot.changes.insertions.map { IndexPath(item: dataSourceSnapshot.after.firstIndex(of: $0)!, section: 0)}, with: .automatic)
            self.tableView.deleteRows(at: dataSourceSnapshot.changes.deletions.map { IndexPath(item: dataSourceSnapshot.before.firstIndex(of: $0)!, section: 0)}, with: .automatic)
            self.tableView.reloadRows(at: dataSourceSnapshot.changes.modifications.map { IndexPath(item: dataSourceSnapshot.after.firstIndex(of: $0)!, section: 0)}, with: .automatic)
        }, completion: nil)
    })
    .listen()

Relationship between Document and Object

Document is a class that inherits Object. For simple operations, it is enough to use Document.

public final class Document<Model: Modelable & Codable>: Object, DataRepresentable, DataCacheable {

    public var data: Model?
    
}

You can perform complex operations by extending Object and defining your own class. Use examples are explained in Using Ballcap with SwiftUI

Migrate from Pring

Overview

The difference from Pring is that ReferenceCollection and NestedCollection have been abolished. In Pring, adding a child Object to the ReferenceCollection and NestedCollection of the parent Object saved the parent Object at the same time when it was saved. Ballcap requires the developer to save SubCollection using Batch. In addition, Pring also saved the File at the same time as the Object with the File was saved. Ballcap requires that developers save files using StorageBatch.

Scheme

Ballcap can handle Object class by inheriting Object class like Pring. If you inherit Object class, you must conform to DataRepresentable.

class Room: Object, DataRepresentable {

    var data: Model?

    struct Model: Modelable & Codable {
        var members: [String] = []
    }
}

SubCollection

Ballcap has discontinued NestedCollection and ReferenceCollection Class. Instead, it represents SubCollection by defining CollectionKeys.

Class must match HierarchicalStructurable to use CollectionKeys.

class Room: Object, DataRepresentable & HierarchicalStructurable {

    var data: Model?
    
    var transcripts: [Transcript] = []

    struct Model: Modelable & Codable {
        var members: [String] = []
    }

    enum CollectionKeys: String {
        case transcripts
    }
}

Use the collection function to access the SubCollection.

let collectionReference: CollectionReference = obj.collection(path: .transcripts)

SubCollection's Document save

let batch: Batch = Batch()
let room: Room = Room()
batch.save(room.transcripts, to: room.collection(path: .transcripts))
batch.commit()

Using Ballcap with SwiftUI

First, create an object that conforms to ObservableObject. DataListenable makes an Object observable.

final class User: Object, DataRepresentable, DataListenable, ObservableObject, Identifiable {

    typealias ID = String

    override class var name: String { "users" }

    struct Model: Codable, Modelable {

        var name: String = ""
    }

    @Published var data: User.Model?

    var listener: ListenerRegistration?
}

Next, create a View that displays this object.

struct UserView: View {

    @ObservedObject var user: User

    @State var isPresented: Bool = false

    var body: some View {
        VStack {
            Text(user[\.name])
        }
        .navigationBarTitle(Text("User"))
        .navigationBarItems(trailing: Button("Edit") {
            self.isPresented.toggle()
        })
        .sheet(isPresented: $isPresented) {
            UserEditView(user: self.user.copy(), isPresented: self.$isPresented)
        }
        .onAppear {
            _ = self.user.listen()
        }
    }
}

You can access the object data using subscript.

Text(user[\.name])

Start user observation with onAppear.

.onAppear {
    _ = self.user.listen()
}

Copy object

Pass a copy of Object to EditView before editing the data.

.sheet(isPresented: $isPresented) {
    UserEditView(user: self.user.copy(), isPresented: self.$isPresented)
}

Since the Object is being observed by the listener, changes can be caught automatically.

Finally, create a view that can update the object.

struct UserEditView: View {

    @ObservedObject var user: User

    @Binding var isPresented: Bool

    var body: some View {

        VStack {

            Form {
                Section(header: Text("Name")) {
                    TextField("Name", text: $user[\.name])
                }
            }

            Button("Save") {
                self.user.update()
                self.isPresented.toggle()
            }
        }.frame(height: 200)
    }
}

Updating an object is possible only with update().

Button("Update") {
    self.user.update()
    self.isPresented.toggle()
}
Comments
  • Object' does not conform to protocol 'Modelable'

    Object' does not conform to protocol 'Modelable'

    Describe the bug

    A clear and concise description of what the bug is.

    [REQUIRED] Step 1: Describe your environment

    • Xcode version: _____
    • Pring version: _____

    [REQUIRED] Step 3: Describe the problem

    Steps to reproduce:

    What happened? How can we make the problem occur? This could be a description, log/console output, etc.

    Relevant Code:

    // TODO(you): code here to reproduce the problem
    
    opened by SebastianBO 16
  • How to remove document<>

    How to remove document<>

    image

    print(Document<User>.modelName) // user
    

    I'm a Pring user. I appreciate it.

    ModelName is user, but collection name is document<user>. In case of Pring, collection name is user. Is this a Ballcap's feature? Can I change collection name without overriding Document class?

    opened by kot10n5tn 7
  • DataSource updates not working for last deleted document in collection

    DataSource updates not working for last deleted document in collection

    Describe the bug

    When deleting last document in collection, DataSource not picking up changes and do not notify about removed items.

    [REQUIRED] Step 1: Describe your environment

    • Xcode version: 10.3 * Ballcap version: 0.10.4

    [REQUIRED] Step 3: Describe the problem

    If last document in collection deleted snapshot is not processed. Issue caused by this line. https://github.com/1amageek/Ballcap-iOS/blob/cd943d1add107d477d56e5dbb8761b80f3dadb1c/Ballcap/DataSource.swift#L146 When deleting last document lastSnapshot is nil and self._execute(snapshot: snapshot) not getting called.

    opened by mikhailmulyar 2
  • FR: DataSource support BindableObject

    FR: DataSource support BindableObject

    Consider correspondence of BindableObject in order to correspond to SwiftUI seamlessly

    https://developer.apple.com/documentation/swiftui/bindableobject

    opened by 1amageek 2
  • Consider adding to firebaseopensource.com

    Consider adding to firebaseopensource.com

    opened by thatfiredev 1
  • update example so Users view listens to changes

    update example so Users view listens to changes

    Hi, thought it might be helpful if the example WithSwiftUI was extended a bit as I'm learning more about Ballcap. There is one issue that still needs fixing though, and I'd love your thoughts on best way to fix:

    If you tap on a user and edit their name, after clicking save UserView correctly shows the updates. The app running on a separate iPhone in the Users (ContentView) or UserView will also show the updates correctly. However, if on the iPhone where the edit was made you go back to the Users list, the list still shows the previous state of the name property, prior to the edit. I'll look at the code more closely, but if you had any thoughts on your preferred way to fix this bug, please let me know.

    Thank you for your effort to code up such a nice library.

    Kimon

    opened by kinergy 1
  • configure is inaccessible

    configure is inaccessible

    Describe the bug

    BallcapApp.configure showing the message "inaccessible due to internal protection level message".

    [REQUIRED] Step 1: Describe your environment

    • Xcode version: 10.2.1
    • Bellcap version: 0.6.0

    [REQUIRED] Step 3: Describe the problem

    Steps to reproduce:

    Put BallcapApp.configure in a class and after try to compile.

    Relevant Code:

    BallcapApp.configure(Firestore.firestore().document("version/1"))
    
    opened by priore 1
  • documentReference issue

    documentReference issue

    Why this is not referenced to path?

    static var documentReference: DocumentReference { return Firestore.firestore().document("version/(self.modelVersion)") }

    opened by brightsider 1
  • FIRQuerySnapshotBlock is unavailable in Swift

    FIRQuerySnapshotBlock is unavailable in Swift

    I just made a pod update and am now using Firebase 10.1.0 and Ballcap 1.3.5 but when trying to build my app I get build errors inside Ballcaps Query.swift in lines 119 - 125.

            public func listen(includeMetadataChanges: Bool = true, listener: @escaping FIRQuerySnapshotBlock) -> ListenerRegistration {
                return query.addSnapshotListener(includeMetadataChanges: includeMetadataChanges, listener: listener)
            }
    
            public func get(completion: @escaping FIRQuerySnapshotBlock) {
                query.getDocuments(completion: completion)
            }
    

    The error is for both functions

    'FIRQuerySnapshotBlock' is unavailable in Swift: Use Swift's closure syntax instead.
    

    Does anyone else have the problem?

    I'm using:

    • Xcode 14.0.1
    • Cocoapods 1.11.3
    • Firebase 10.1.0
    • Ballcap 1.3.5
    opened by DanielLeberle 0
  • Is it possible to remove a field from a document

    Is it possible to remove a field from a document

    I'm using Ballcap in a SwiftUI environment and I have a class that contains an optional field of type DocumentReference in its Model. Initially the field does not exist but I can set it through the UI of my app. This works just as expected. But I would like to be able to also remove the reference. I tried setting it to nil but this doesn't work unfortunately.

    Is there currently any way to achieve this with Ballcap?

    Thanks for your help!

    opened by DanielLeberle 0
  • Allow initialization of Object subclasses with models

    Allow initialization of Object subclasses with models

    Is your feature request related to a problem? Please describe. Model's of Object subclasses require empty init methods:

    class User: Object, DataRepresentable {
        var data: Model?
        
        struct Model: Modelable, Codable {
            let id: String
            let firstName: String
            let lastName: String
            
            init() {
                self.id = ""
                self.firstName = ""
                self.lastName = ""
            }
            
            init(id: String, firstName: String, lastName: String) {
                self.id = id
                self.firstName = firstName
                self.lastName = lastName
            }
        }
    }
    

    And when used require doing a little dance with initializing separately and assigning:

    let user = User()
    let model = User.Model(id: userId,
                               firstName: firstName,
                               lastName: lastName)
    user.data = model
    user.save()
    

    This is un-ideal as you need to write so much repetitive boilerplate for every Object subclass, and you can forget to assign the model to object.data.

    Describe the solution you'd like When initializing an instance of a subclass of Object it would be great if we required the data model to be provided along with it:

    let model = User.Model(id: userId,
                               firstName: firstName,
                               lastName: lastName)
    let user = User(data: model)
    user.save()
    

    Which would enable us to simplify the model blueprint to:

    class User: Object, DataRepresentable {
        var data: Model?
        
        struct Model: Modelable, Codable {
            let id: String
            let firstName: String
            let lastName: String
        }
    }
    

    Describe alternatives you've considered I listed the alternative route I'm using above.

    Additional context I'd be happy to help develop this if you think it would be a worthwhile feature.

    opened by scottfister 0
  • WithSwiftUI Sample Crash

    WithSwiftUI Sample Crash

    Describe the bug

    WithSwiftUI example crashing on run.

    [REQUIRED] Step 1: Describe your environment

    • Xcode version: Version 11.3 (11C29)
    • Ballcap version: master

    [REQUIRED] Step 3: Describe the problem

    Example not compiling

    Steps to reproduce:

    Clone repo Change directory to example/SwiftUI pod install Copy over GoogleService-Info.plist (works on other projects)

    Error Message

    2020-01-15 02:51:53.892641-0800 WithSwiftUI[3613:4281424]  - <AppMeasurement>[I-ACS036002] Analytics screen reporting is enabled. Call +[FIRAnalytics setScreenName:setScreenClass:] to set the screen name or override the default screen class name. To disable screen reporting, set the flag FirebaseScreenReportingEnabled to NO (boolean) in the Info.plist
    2020-01-15 02:51:53.958240-0800 WithSwiftUI[3613:4281430] 6.11.0 - [Firebase/Analytics][I-ACS023007] Analytics v.60103000 started
    2020-01-15 02:51:53.958820-0800 WithSwiftUI[3613:4281430] 6.11.0 - [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see http://goo.gl/RfcP7r)
    keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"name\", intValue: nil) (\"name\").", underlyingError: nil))
    Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /path/to/Ballcap-iOS/examples/WithSwiftUI/Pods/Ballcap/Ballcap/DataSource.swift, line 191
    2020-01-15 02:51:54.117454-0800 WithSwiftUI[3613:4281428] Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /path/to/Ballcap-iOS/examples/WithSwiftUI/Pods/Ballcap/Ballcap/DataSource.swift, line 191
    
    opened by naturalui 0
  • A way to avoid Firestore crash

    A way to avoid Firestore crash

    Hello. I'll be very happy if you could help me with avoiding firebase crash in a module!

    I'm trying to make a framework that wraps Firestore SDK, but it crashes. According to some comments on GitHub, using Firebase from multiple modules have some difficulties.

    Firebase is a linked statically and can only be linked once into an app. It cannot be linked into multiple dynamic frameworks.

    from https://github.com/firebase/firebase-ios-sdk/issues/4263#issuecomment-551209077

    My crash seems to be the same as this issue: https://github.com/firebase/firebase-ios-sdk/issues/4271

    I'm interested in how Ballcap-iOS avoid this problem since it wraps Firestore in a module. Do you know how Ballcap-iOS avoids this problem?

    I've uploaded my sample app which has the same crash. It crashes by executing tests. https://github.com/yoching/FirestoreDependencyExperiment

    Thank you!

    opened by yoching 0
Owner
1amageek
@1amageek
1amageek
Aplikasi iOS Simulasi CRUD Stok Barang dengan SwiftUI, Firebase CLI & Firestore

iStockery Aplikasi iStockery adalah aplikasi stok inventory berbasis iOS yang dibuat menggunakan Firebase (Firestore) secara Local dengan fitur CRUD d

DK 7 Aug 1, 2022
Swift UIKit E-Commerce (UgurShopping) No StoryBoard Firebase, FireStore, FirebaseAuth, KingFisher, SwiftEntryKit, ProgressHud, Alamofire UICollectionViewCompositionalLayout, NotificationCenter

Swift UIKit E-Commerce (UgurShopping) No StoryBoard Firebase, FireStore, FirebaseAuth, KingFisher, SwiftEntryKit, ProgressHud, Alamofire UICollectionViewCompositionalLayout, NotificationCenter

Ugur Hamzaoglu 2 Oct 16, 2022
Warning pushNotification - Using push notification with Firebase Cloud Messaging

재난문자 푸시 알림 구현 1) 구현 기능 2) 기본 개념 (1) Remote Notification 불시에 발생한 업데이트 불특정 시간 예측 불

null 0 Jan 24, 2022
Firebase Analytics Firebase Notification Alamofire KingFisher Ombdb API

MovieOmdbApp Firebase Analytics Firebase Notification Alamofire KingFisher Ombdb

Kaya 0 Dec 20, 2021
Realtime Database and Firestore parser

Columbina's FirebaseParser Easy parsing for Firebase Realtime Database or Firestore. Dealing with Firebase documents might be tricky. Since it doesn't

Columbina 2 Mar 23, 2022
A macOS auxiliary app to choose results from cloud input methods

CloudInputAssist Introduction 介绍 一个 macOS 辅助应用程序,用于使用云输入法(例如谷歌云输入法)API 提供辅助的候选词结果。 Motivation 动机 使用不联网的本地输入法时,长句的候选词往往不太理想,尤其是使用双拼输入时。这种情况下,借助一些输入法的云计

JJAYCHEN 1 Jan 3, 2023
iOS Open-Source Telematics App with Firebase© integration

Open-source telematics app for iOS. The application is suitable for UBI (Usage-based insurance), shared mobility, transportation, safe driving, tracking, family trackers, drive-coach, and other driving mobile applications

Damoov 17 Dec 11, 2022
The app demonstrates how to use Firebase in a SwiftUI iOS app

Firebase SwiftUIDemo app This app demonstrates how to use Firebase in a SwiftUI iOS app. Firebase Setup Go to firebase.com Click new project. Copy app

Andrew Gholson 0 Nov 28, 2021
Firebase Quickstart Samples for iOS

Firebase Quickstarts for iOS A collection of quickstart samples demonstrating the Firebase APIs on iOS. Each sample contains targets for both Objectiv

Firebase 2.5k Jan 1, 2023
IOS mobile application that uses URLSession and Firebase

DogApp IOS mobile application that uses URLSession and Firebase. First a dog ima

null 0 Feb 13, 2022
Food Order App for iOS. VIPER pattern, Alamofire and Firebase used.

Nibble Yemek Sipariş Uygulaması Techcareer.net Techmasters IOS Bootcamp bitirme ödevi için hazırladığım bir yemek sipariş uygulaması. API KEY SON GEÇE

null 2 Sep 20, 2022
Simple Todo Application using SwiftUI / Firebase / Redux.

Simple Todo Application using SwiftUI/Firebase/Redux/Combine. Light _ _ _ _ Dark _ _ _ Feature Use SwiftUI fully. Use Firebase. Authentication Cloud F

Suguru Kishimoto 337 Dec 25, 2022
Completed Project for Authentication in SwiftUI using Firebase Auth SDK & Sign in with Apple

Completed Project for Authentication in SwiftUI using Firebase Auth SDK & Sign in with Apple Follow the tutorial at alfianlosari.com Features Uses Fir

Alfian Losari 43 Dec 22, 2022
SwiftUI, Firebase, Kingfisher, googleapis

SwiftUI-KokaiByWGO Xcode Version 12.0 SwiftUI, Firebase, Kingfisher, googleapis Learn Thai with pictures and sounds Note : This version have no CMS so

Waleerat S. 0 Oct 6, 2021
Social Media platform build with swiftUI and Firebase with google and apple account integration for Signing In Users

Social Media platform build with swiftUI and Firebase with google and apple account integration for Signing In Users . Providing Users availability to upload posts and images add caption allowing other users to comment , with Find section to explore new people , new stories , User Profile section to allow the user to take control of his account .

Devang Papinwar 2 Jul 11, 2022
Instagram clone with firebase and swift

Instagram clone with firebase and swift

Murat Çiçek 1 Nov 20, 2021
A grocery list app for families written in Swift using Firebase Realtime Database

FamiList | Grocery list app in Swift FamiList is a grocery list app for families written in Swift using Firebase Realtime Database. You can add differ

Wasan Ibrahim 2 Jul 31, 2022
The ToDoList application using FireBase allows you to register users

ToDoFirebase Приложение ToDoList с использовавнием FireBase позволяет зарегистри

Vasiliy Chistyakov 0 Dec 19, 2021
A detailed clone of the Instagram app built with Firebase

[This repository is no longer being maintained] InstagramClone A detailed clone

null 0 Dec 26, 2021