Giter Site home page Giter Site logo

urban-health-labs / combinefirebase Goto Github PK

View Code? Open in Web Editor NEW
223.0 9.0 46.0 28.28 MB

Combine wrapper on Google's iOS Firebase library.

License: MIT License

Ruby 16.44% Swift 83.56%
firebase firebase-firestore ios ios13 swift5-1 swift combine-framework firebase-storage firebase-realtime-database storage database firebase-db firestore remoteconfig combine swiftui publisher apple google firebase-functions

combinefirebase's Introduction

CombineFirebase

SwiftPM compatible Version License Platform

Handling Firebase asynchronous callbacks with Combine framework.

Example

To run the example project, clone the repo, and run pod install from the Example directory first. See Usage below for more information.

Requirements

  • Xcode 11.3+ | Swift 5.1+
  • iOS 13.0+ | tvOS 13.0+ | macOS 10.15+

Installation

CocoaPods

CombineFirebase is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'CombineFirebase/Firestore'
pod 'CombineFirebase/RemoteConfig'
pod 'CombineFirebase/Database'
pod 'CombineFirebase/Storage'
pod 'CombineFirebase/Auth'
pod 'CombineFirebase/Functions'

Swift Package Manager

CombineFirebase is available through Swift Package Manager in beta status. To install it, you must have Xcode 12.0 and above, simply add CombineFirebase to an existing Xcode project as a package dependency:

  1. From the File menu, select Swift Packages > Add Package Dependency...
  2. Enter https://github.com/rever-ai/CombineFirebase into the package repository URL text field.
  3. Xcode should choose updates package up to the next version option by default.

Usage

import CombineFirebase
import Firebase
import Combine

Database

Basic write operation

var cancelBag = Set<AnyCancellable>()

func setUserData() {
    let ref = Database.database().reference()

    ref.child("users")
        .child("1")
        .setValue(["username": "Arnonymous"])
        .sink { _ in
            print("Document successfully updated")
        }.store(in: &cancelBag)
}

// https://firebase.google.com/docs/database/ios/read-and-write#basic_write

Listen for value events

var cancelBag = Set<AnyCancellable>()

func listenForValueEvent() {
    let ref = Database.database().reference()

    ref.child("users")
        .child("1")
        .publisher(.value)
        .receive(on: RunLoop.main)
        .sink { snapshot in
            print("Value:\(snapshot.value)")
        }.store(in: &cancelBag)
}
    
// https://firebase.google.com/docs/database/ios/read-and-write#listen_for_value_events

Read data once

var cancelBag = Set<AnyCancellable>()

func readDataOnce() {
    let ref = Database.database().reference()

    ref.child("users")
        .child("1")
        .observeSingleEvent(.value)
        .receive(on: RunLoop.main)                
        .sink { snapshot in
            print("Value:\(snapshot.value)")
        }.store(in: &cancelBag)
}
    
// https://firebase.google.com/docs/database/ios/read-and-write#read_data_once

Update specific fields

var cancelBag = Set<AnyCancellable>()

func updateFields() {
    let ref = Database.database().reference()

    let childUpdates = ["/posts/\(key)": post,
                        "/user-posts/\(userID)/\(key)/": post]
    ref.updateChildValues(childUpdates)
        .receive(on: RunLoop.main)
        .sink { _ in
            // Success
        }.store(in: &cancelBag)
}

// https://firebase.google.com/docs/database/ios/read-and-write#update_specific_fields

Delete data

var cancelBag = Set<AnyCancellable>()

func deleteData() {
    let ref = Database.database().reference()

    ref.removeValue()
        .receive(on: RunLoop.main)    
        .sink { _ in
            // Success
        }.store(in: &cancelBag)
}
    
// https://firebase.google.com/docs/database/ios/read-and-write#delete_data

Save data as transactions

var cancelBag = Set<AnyCancellable>()

func saveDataAsTransaction() {
    let ref = Database.database().reference()

    ref.runTransactionBlock { currentData in
            // TransactionResult
        }.sink { _ in
            // Success
        }.store(in: &cancelBag)
}
    
// https://firebase.google.com/docs/database/ios/read-and-write#save_data_as_transactions

Firestore

Setting data

var cancelBag = Set<Cancellable>()

let db = Firestore.firestore()

struct City: Codable {
    var name: String? = nil
    var state: String? = nil
    var country: String? = nil
    var capital: String? = nil
    var population: Int? = nil
    
    // local variable 
    var id: String? = nil
}

func setSanFranciscoData(city: City) {
    let onErrorCompletion: ((Subscribers.Completion<Error>) -> Void)? = { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): print("โ—๏ธ failure: \(error)")
        }
    }

    let onValue: (Void) -> Void = {
        print("โœ… value")
    }

    // Add a new document in collection "cities"
    (db.collection("cities")
        .document("SF")
        .setData(from: city) as AnyPublisher<Void, Error>) // Note: you can use (as Void) for simple setData({})
            .sink(receiveCompletion: onErrorCompletion, receiveValue: onValue)
            .store(in: &cancelBag)
}
       
// Add a new document with a generated id.
func addSanFranciscoDocument(city: City) {
    (db.collection("cities")
        .addDocument(data: [
            "name": "San Francisco",
            "state": "CA",
            "country": "USA",
            "capital": false,
            "population": 860000
            ]) as AnyPublisher<DocumentReference, Error>)
            .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }) { ref in
                print("Document added with ID: \(ref.documentID)")
            }
            .store(in: &cancelBag)            
}
        
// Set the "capital" field of the city 'SF'
func updateSanFranciscoDocument() {
    (db.collection("cities")
        .document("SF")
        .updateData([
            "capital": true
            ]) as AnyPublisher<Void, Error>)
            .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print(i"โ—๏ธ failure: \(error)")
            }) { _ in }
            .store(in: &cancelBag)
}
        
// https://firebase.google.com/docs/firestore/manage-data/add-data

Get a document

func getDocument() {
    db.collection("cities")
        .document("SF")
        .getDocument()
        .sink(receiveCompletion: { (completion) in
               switch completion {
               case .finished: print("๐Ÿ finished")
               case .failure(let error): print("โ—๏ธ failure: \(error)")
               }
           }) { document in
               print("Document data: \(document.data())")
        }
        .store(in: &cancelBag)
}

func getDocumentAsObject() {
    db.collection("cities")
        .document("SF")
        .getDocument(as: City.self)
        .sink(receiveCompletion: { (completion) in
               switch completion {
               case .finished: print("๐Ÿ finished")
               case .failure(let error): print("โ—๏ธ failure: \(error)")
               }
           }) { city in
               print("City: \(city)")
        }
        .store(in: &cancelBag)
}
    
// https://firebase.google.com/docs/firestore/query-data/get-data

Get Realtime updates

let db = Firestore.firestore()

// Document
func listenDocument() {
    db.collection("cities")
        .document("SF")
        .publisher()
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }
        }) { document in
            print("Document data: \(document.data())")
        }
        .store(in: &cancelBag)
}

var cityDocumentSnapshotMapper: (DocumentSnapshot) throws -> City? {
    {
        var city =  try $0.data(as: City.self)
        city.id = $0.documentID
        return city
    }
}

func listenDocumentAsObject() {
    db.collection("cities")
        .document("SF")
        .publisher(as: City.self, documentSnapshotMapper: cityDocumentSnapshotMapper)
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }
        }) { city in
            print("City: \(city)")
        }
        .store(in: &cancelBag)
}

    
// Collection
func listenCollection() {
    db.collection("cities")
        .publisher()
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }
        }) { snapshot in
            print("collection data: \(snapshot.documents)")
        }.store(in: &cancelBag)
}

func listenCollectionAsObject() {
    db.collection("cities")
        .publisher(as: City.self, documentSnapshotMapper: cityDocumentSnapshotMapper)
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }
        }) { cities in
            print("Cities: \(cities)")
        }.store(in: &cancelBag)
}

// https://firebase.google.com/docs/firestore/query-data/listen

Batched writes

var cancelBag = Set<AnyCancellable>()

func batchWrite() {
    let db = Firestore.firestore()

    // Get new write batch
    let batch = db.batch()

    // Update the population of 'SF'
    let sfRef = db.collection("cities").document("SF")
    batch.updateData(["population": 1000000 ], forDocument: sfRef)

    // Commit the batch
    batch.commit()
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }
        }) { _ in}
        .store(in: &cancelBag)
}
    
// https://firebase.google.com/docs/firestore/manage-data/transactions

Transactions

var cancelBag = Set<AnyCancellable>()

func transaction() {
    let db = Firestore.firestore()
    let sfReference = db.collection("cities").document("SF")

    (db.runTransaction { transaction in
        let sfDocument = try transaction.getDocument(sfReference)
        
        guard let oldPopulation = sfDocument.data()?["population"] as? Int else {
            let error = NSError(
                domain: "AppErrorDomain",
                code: -1,
                userInfo: [
                    NSLocalizedDescriptionKey: "Unable to retrieve population from snapshot \(sfDocument)"
                ]
            )
            throw error
        }
        
        transaction.updateData(["population": oldPopulation + 1], forDocument: sfReference)
        return nil
        } as AnyPublisher<Any?, Error>)
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }
        }) { _ in
            print("Transaction successfully committed!")
        }
        .store(in: &cancelBag)
}
    
// https://firebase.google.com/docs/firestore/manage-data/transactions

RemoteConfig

Fetch

// TimeInterval is set to expirationDuration here, indicating the next fetch request will use
// data fetched from the Remote Config service, rather than cached parameter values, if cached
// parameter values are more than expirationDuration seconds old. See Best Practices in the
// README for more information.

var cancelBag = Set<AnyCancellable>()

func fetchRemoteConfig() {
    (RemoteConfig.remoteConfig()
        .fetch(withExpirationDuration: TimeInterval(expirationDuration), activateFetched: true) as AnyPublisher<RemoteConfigFetchStatus, Error>)
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }
        }) { status in
            print("Config fetched! with success:\(status == .success)")
        }
       .store(in: &cancelBag)
}

// https://firebase.google.com/docs/remote-config/ios

Storage

Upload

var cancelBag = Set<AnyCancellable>()

let reference = Storage.storage()
    .reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
    
let data: Data // Upload data
(reference.putData(data) as AnyPublisher<StorageMetadata, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { metadata in
        // Success         
    }
    .store(in: &cancelBag)
    

let fileURL: URL // Upload file
(reference.putFile(from: fileURL) as AnyPublisher<StorageMetadata, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { metadata in
       // Success         
    }
    .store(in: &cancelBag)

Observe events

var cancelBag = Set<AnyCancellable>()
let reference = Storage.storage()
    .reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")

let fileURL: URL // Upload file
let uploadTask = reference.putFile(from: fileURL)

// Listen for state changes
uploadTask.publisher(.progress)
    .sink(receiveCompletion: { _ in
        print("๐Ÿ finished")
    }) { snapshot in
        if let error = snapshot.error {
            print("error: \(error)")
        }
        // Upload reported progress
        let percentComplete = 100.0 * Double(snapshot.progress?.completedUnitCount ?? 0)
                                    / Double(snapshot.progress.totalUnitCount ?? 1)
   }
   .store(in: &cancelBag)

Download

var cancelBag = Set<AnyCancellable>()
let reference = Storage.storage()
    .reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")

// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
(reference.getData(maxSize: 1 * 1024 * 1024) as AnyPublisher<Data, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { data in
       // Data for "images/space.jpg" is returned
    }
    .store(in: &cancelBag)
    
// Create local filesystem URL
let localURL = URL(string: "path/to/image")!
    
// Download to the local filesystem
(reference.write(toFile: localURL) as AnyPublisher<URL, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { data in
       // Local file URL for "images/space.jpg" is returned
    }
    .store(in: &cancelBag)

URL

var cancelBag = Set<AnyCancellable>()
let reference = Storage.storage()
    .reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
    
// Fetch the download URL
(reference.downloadURL() as AnyPublisher<URL, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { data in
        // Get the download URL for 'images/space.jpg'       
    }
    .store(in: &cancelBag)

Metadata

var cancelBag = Set<AnyCancellable>()
let reference = Storage.storage()
    .reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
    
// Create file metadata to update
let newMetadata = StorageMetadata()
    
// Update metadata properties
(reference.updateMetadata(newMetadata) as AnyPublisher<StorageMetadata, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { metadata in
        // Updated metadata for 'images/space.jpg' is returned        
    }
    .store(in: &cancelBag)
    
// Get metadata properties
(reference.getMetadata() as AnyPublisher<StorageMetadata, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { metadata in
        // Metadata now contains the metadata for 'images/space.jpg'
    }
    .store(in: &cancelBag)

Delete

var cancelBag = Set<AnyCancellable>()
let reference = Storage.storage()
    .reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
    
// Delete the file
(reference.delete() as AnyPublisher<Void, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { _ in
        // File deleted successfully    
    }
    .store(in: &cancelBag)

Auth

Create

var cancelBag = Set<AnyCancellable>()
let auth = Auth.auth()
    
// Create a password-based account
(auth.createUser(withEmail: "[email protected]", password: "1q2w3e4r") as AnyPublisher<AuthDataResult, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { _ in
        // User signed in
    }.store(in: &cancelBag)

// https://firebase.google.com/docs/auth/ios/password-auth

Sign in

var cancelBag = Set<AnyCancellable>()

let auth = Auth.auth()
    
// Sign in a user with an email address and password
(auth.signIn(withEmail: "[email protected]", password: "1q2w3e4r") as AnyPublisher<AuthDataResult, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { _ in
        // User signed in
    }.store(in: &cancelBag)

// https://firebase.google.com/docs/auth/ios/password-auth

User

Update email

var cancelBag = Set<AnyCancellable>()
let user = Auth.auth().currentUser
    
// Set a user's email address
(user.updateEmail(to: "[email protected]") as AnyPublisher<Void, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { _ in
        // Completed updating Email         
    }.store(in: &cancelBag)

// https://firebase.google.com/docs/auth/ios/manage-users

Delete

var cancelBag = Set<AnyCancellable>()
let user = Auth.auth().currentUser

// Delete a user
(user.delete() as AnyPublisher<Void, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): // Uh-oh, an error occurred! 
        }
    }) { _ in
        // User deleted
    }.store(in: &cancelBag)

// https://firebase.google.com/docs/auth/ios/manage-users

Functions

var cancelBag = Set<AnyCancellable>()
let functions = Functions.functions()
let request = functions.httpsCallable("functionName")

(request
    .call(["parameter": "value"]) as AnyPublisher<HTTPSCallableResult, Error>)
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished: print("๐Ÿ finished")
        case .failure(let error): print("error:\(error)")
        }
    }) { result in
         print("response:\(result)")
    }.store(in: &cancelBag)
    
// https://firebase.google.com/docs/functions/callable#call_the_function

Author

Kumar Shivang, [email protected]

License

CombineFirebase is available under the MIT license. See the LICENSE file for more info.

combinefirebase's People

Contributors

grangej avatar kshivang avatar mdeaconu avatar quanshousio avatar sprzenus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

combinefirebase's Issues

how to use getDocuments?

Hi,

super useful library! I'm trying to get a list of documents.

Looks like there is a getDocuments() function, but

`
environment.service.collection("collections").whereField("userId", isEqualTo: userId)
.getDocuments()
.sink(receiveCompletion: { completion in
switch completion {
case .finished: print("๐Ÿ finished")
case .failure(let error): print("โ—๏ธ failure: (error)")
}
}) { snapshot in
doSomething(snapshot)
}.store(in: &cancelBag)

`
but sink and doSomething are never called even when get
public func getDocuments(source: FirestoreSource = .default) -> AnyPublisher<QuerySnapshot, Error>
returns a successful promise. What am I doing wrong?

getDocuments

Can we extend this functionality to get multiple documents?

Does this Library remove listeners automatically?

@kshivang

According to the Firebase docs

When you are no longer interested in listening to query realtime updates, you must detach your listener so that event callbacks stop. This allows the client to stop using bandwidth to receive updates. 

So I'm curious how is it that CombineFirebase handles this as I can't find any code referencing the removal or detachment of these listeners. I'm concerned with bandwidth usage which can get expensive.

Is CombineFirebase doing this automatically somehow or are we responsible for it?

Update to latest version of Firebase

Firebase has received quite a few updates in the past couple of months. Could you update the Firebase dependency so that it points to the latest version (7.3.1 as of this writing)?

Performing work on non-main queue.

What is the correct way of performing work on a non-main queue using CombineFirebase?

For example, using .getDocument(as:) to transform the data into a model object (in this case City). From the Combine docs it looks like adding subscribe(on:) should ensure the upstream operations are performed on the specified scheduler.
However, when debugging it looks like this is not the case. Is there an issue with my code, or is it related to the implementation of this library? Thanks.

func getDocumentAsObject() {
    db.collection("cities")
        .document("SF")
        .getDocument(as: City.self)
        .subscribe(on: DispatchQueue.global(qos: .userInitiated)) // move upstream work onto non-main thread...
        .sink(receiveCompletion: { (completion) in
               switch completion {
               case .finished: print("๐Ÿ finished")
               case .failure(let error): print("โ—๏ธ failure: \(error)")
               }
           }) { city in
               print("City: \(city)")
        }
        .store(in: &cancelBag)
}

Using CombineFirebase in two targets in one workspace warning

I have app and internal framework which both use CombineFirebase package, something like:

target 'App' do
   pod 'CombineFirebase/Firestore'
end

target 'Framework' do
  pod 'CombineFirebase/Firestore'
end

Whenever I start the app I am getting this warning/error:

objc[57881]: Class PodsDummy_CombineFirebaseFirestore is implemented in both /Users/piotr/Library/Developer/Xcode/DerivedData/App-dbwukpdmwlehcvgucgaodxjqjwty/Build/Products/Debug-iphonesimulator/Framework.framework/Framework (0x10629ce90) and /Users/piotr/Library/Developer/CoreSimulator/Devices/5E6D142F-38F6-46FA-96C6-78D9758B117B/data/Containers/Bundle/Application/8EADBC84-1081-4D49-9633-5AF1E4F16DFF/App.app/App (0x101973a28). One of the two will be used. Which one is undefined.

Not sure if it's some setting coming from the CombineFirebase or something I have to setup in Podfile.

Cannot find publish() function

Apologies if am missing something as a bit of a Combine novice. I have installed CombineFirebase 0.3.0 and Firebase 7.11.1 and am trying to follow the example from the readme file for listening to a collection in Firestore:

import CombineFirebase
import Firebase
import Combine

let db = Firestore.firestore()
var cancelBag = Set<Cancellable>()

func listenCollection() {
    db.collection("cities")
        .publisher()
        .sink(receiveCompletion: { completion in
            switch completion {
            case .finished: print("๐Ÿ finished")
            case .failure(let error): print("โ—๏ธ failure: \(error)")
            }
        }) { snapshot in
            print("collection data: \(snapshot.documents)")
        }.store(in: &cancelBag)
}

However, Swift is unable to find the publisher() method on db.collection("cities") with only a:

publisher(for keyPath: KeyPath<CollectionReference, Value>)

I can see this exists on the Query object on the source code here so am unsure why db.collection("cities") which returns a CollectionReference (which derives from Query) can not find this definition.

No Package.swift manifest for version 0.2.6

Trying to use SPM gives the following error (see screenshot).

I am not sure how to add such a manifest correctly.

Screenshot 2021-04-19 at 14 16 02

I am trying to make CombineFirebase work together with Firebase SDK 7.10.0.

A workarround can be:

Inside XCode, when adding the dependency, chose commit instead of up-to-next-version or branch:

Here is the commit that works: 02bc159

Would be nice if the original dependency URL also does the right thing together with the newest Firebase SDK's.

Oh, and also, it is not yet listet in the Swift Package Index : https://swiftpackageindex.com

Update podspec files

The current release of this library is 0.3.3, but the podspecs list the release versions at 0.2.6. Can these files be updated?

What is the CombineFirebase for?

It would be much better if you could add a piece of summarized information for people who are new on coding like me. Thank you.

'Generic parameter 'Value' could not be inferred'

Thank for uploading this repository.
I used sample code this and get this error.

'Generic parameter 'Value' could not be inferred'

var cancelBag = Set<AnyCancellable>()
let reference = Storage.storage()
    .reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")

let fileURL: URL // Upload file
let uploadTask = reference.putFile(from: fileURL)

// Listen for state changes
uploadTask.publisher(.progress)
    .sink(receiveCompletion: { completion in
       switch completion {
       case .finished: print("๐Ÿ finished")
       case .failure(let error): // Uh-oh, an error occurred! 
       }
   }) { snapshot in
      // Upload reported progress
      let percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount)
      / Double(snapshot.progress!.totalUnitCount)
   }
   .store(in: &cancelBag)

Did you get this kind of error?
And This code need 'break' after 'case .failure(let error)'.๐Ÿ‘

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.