mirror of
https://github.com/caoer/RxFirebase.git
synced 2026-01-12 22:52:01 +08:00
532 lines
13 KiB
Markdown
532 lines
13 KiB
Markdown
# RxFirebase
|
|
|
|
[](https://travis-ci.org/RxSwiftCommunity/RxFirebase)
|
|
[](http://cocoapods.org/pods/RxFirebase)
|
|
[](http://cocoapods.org/pods/RxFirebase)
|
|
[](http://cocoapods.org/pods/RxFirebase)
|
|
|
|
## Requirements
|
|
|
|
Xcode 9.0
|
|
|
|
Swift 4.0
|
|
|
|
## Installation
|
|
|
|
RxFirebase is available through [CocoaPods](http://cocoapods.org). To install
|
|
it, simply add the following lines to your Podfile:
|
|
|
|
```ruby
|
|
pod 'RxFirebase/Firestore'
|
|
pod 'RxFirebase/RemoteConfig'
|
|
pod 'RxFirebase/Database'
|
|
pod 'RxFirebase/Storage'
|
|
pod 'RxFirebase/Auth'
|
|
pod 'RxFirebase/Functions'
|
|
```
|
|
|
|
## Usage
|
|
|
|
```swift
|
|
import RxFirebase
|
|
```
|
|
|
|
- [Database](#database)
|
|
- [Firestore](#firestore)
|
|
- [RemoteConfig](#remoteconfig)
|
|
- [Storage](#storage)
|
|
- [Auth](#auth)
|
|
- [Functions](#functions)
|
|
|
|
### Database
|
|
|
|
Basic write operation:
|
|
```swift
|
|
let ref = Database.database().reference()
|
|
|
|
ref.child("users")
|
|
.child("1")
|
|
.rx
|
|
.setValue(["username": "Arnonymous"])
|
|
.subscribe(onNext: { _ in
|
|
print("Document successfully updated")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/database/ios/read-and-write#basic_write
|
|
```
|
|
|
|
Listen for value events:
|
|
```swift
|
|
let ref = Database.database().reference()
|
|
|
|
ref.child("users")
|
|
.child("1")
|
|
.rx
|
|
.observeEvent(.value)
|
|
.subscribe(onNext: { snapshot in
|
|
print("Value:\(snapshot.value)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/database/ios/read-and-write#listen_for_value_events
|
|
```
|
|
|
|
Read data once:
|
|
```swift
|
|
let ref = Database.database().reference()
|
|
|
|
ref.child("users")
|
|
.child("1")
|
|
.rx
|
|
.observeSingleEvent(.value)
|
|
.subscribe(onNext: { snapshot in
|
|
print("Value:\(snapshot.value)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/database/ios/read-and-write#read_data_once
|
|
```
|
|
|
|
Update specific fields:
|
|
```swift
|
|
let ref = Database.database().reference()
|
|
|
|
let childUpdates = ["/posts/\(key)": post,
|
|
"/user-posts/\(userID)/\(key)/": post]
|
|
ref.rx.updateChildValues(childUpdates)
|
|
.subscribe(onNext: { _ in
|
|
// Success
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/database/ios/read-and-write#update_specific_fields
|
|
```
|
|
|
|
Delete data:
|
|
```swift
|
|
let ref = Database.database().reference()
|
|
|
|
ref.rx.removeValue()
|
|
.subscribe(onNext: { _ in
|
|
// Success
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/database/ios/read-and-write#delete_data
|
|
```
|
|
|
|
Save data as transactions
|
|
```swift
|
|
let ref = Database.database().reference()
|
|
|
|
ref.rx.runTransactionBlock { currentData in
|
|
// TransactionResult
|
|
}.subscribe(onNext: { _ in
|
|
// Success
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/database/ios/read-and-write#save_data_as_transactions
|
|
```
|
|
|
|
### Firestore
|
|
|
|
Setting data:
|
|
```swift
|
|
let db = Firestore.firestore()
|
|
|
|
// Add a new document in collection "cities"
|
|
db.collection("cities")
|
|
.document("SF")
|
|
.rx
|
|
.setData([
|
|
"name": "San Francisco",
|
|
"state": "CA",
|
|
"country": "USA",
|
|
"capital": false,
|
|
"population": 860000
|
|
]).subscribe(onError: { error in
|
|
print("Error setting data: \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Add a new document with a generated id.
|
|
db.collection("cities")
|
|
.rx
|
|
.addDocument(data: [
|
|
"name": "San Francisco",
|
|
"state": "CA",
|
|
"country": "USA",
|
|
"capital": false,
|
|
"population": 860000
|
|
]).subscribe(onNext: { ref in
|
|
print("Document added with ID: \(ref.documentID)")
|
|
}, onError: { error in
|
|
print("Error adding document: \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Set the "capital" field of the city 'SF'
|
|
db.collection("cities")
|
|
.document("SF")
|
|
.rx
|
|
.updateData([
|
|
"capital": true
|
|
]).subscribe(onNext: {
|
|
print("Document successfully updated")
|
|
}, onError: { error in
|
|
print("Error updating document: \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/firestore/manage-data/add-data
|
|
```
|
|
|
|
Get a document:
|
|
```swift
|
|
let db = Firestore.firestore()
|
|
|
|
db.collection("cities")
|
|
.document("SF")
|
|
.rx
|
|
.getDocument()
|
|
.subscribe(onNext: { document in
|
|
if let document = document {
|
|
print("Document data: \(document.data())")
|
|
} else {
|
|
print("Document does not exist")
|
|
}
|
|
}, onError: { error in
|
|
print("Error fetching snapshots: \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/firestore/query-data/get-data
|
|
```
|
|
|
|
Get Realtime Updates:
|
|
```swift
|
|
let db = Firestore.firestore()
|
|
|
|
// Document
|
|
db.collection("cities")
|
|
.document("SF")
|
|
.rx
|
|
.listen()
|
|
.subscribe(onNext: { document in
|
|
print("Current data: \(document.data())")
|
|
}, onError: { error in
|
|
print("Error fetching snapshots: \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// Collection
|
|
db.collection("cities")
|
|
.rx
|
|
.listen()
|
|
.subscribe(onNext: { snapshot in
|
|
snapshot.documentChanges.forEach { diff in
|
|
if (diff.type == .added) {
|
|
print("New city: \(diff.document.data())")
|
|
}
|
|
if (diff.type == .modified) {
|
|
print("Modified city: \(diff.document.data())")
|
|
}
|
|
if (diff.type == .removed) {
|
|
print("Removed city: \(diff.document.data())")
|
|
}
|
|
}
|
|
}, onError: { error in
|
|
print("Error fetching snapshots: \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/firestore/query-data/listen
|
|
```
|
|
|
|
Batched writes:
|
|
```swift
|
|
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.rx
|
|
.commit()
|
|
.subscribe(onNext: {
|
|
print("Batch write succeeded.")
|
|
}, onError: { error in
|
|
print("Error writing batch \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/firestore/manage-data/transactions
|
|
```
|
|
|
|
Transactions:
|
|
```swift
|
|
let db = Firestore.firestore()
|
|
let sfReference = db.collection("cities").document("SF")
|
|
|
|
db.rx.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
|
|
}.subscribe(onNext: { _ in
|
|
print("Transaction successfully committed!")
|
|
}, onError: { error in
|
|
print("Transaction failed: \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/firestore/manage-data/transactions
|
|
```
|
|
|
|
### RemoteConfig
|
|
|
|
Fetch:
|
|
```swift
|
|
// 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.
|
|
RemoteConfig.remoteConfig()
|
|
.rx
|
|
.fetch(withExpirationDuration: TimeInterval(expirationDuration), activateFetched: true)
|
|
.subscribe(onNext: { status in
|
|
print("Config fetched! with success:\(status == .success)")
|
|
}, onError: { error in
|
|
print("Error: \(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/remote-config/ios
|
|
```
|
|
|
|
### Storage
|
|
|
|
Upload:
|
|
```swift
|
|
|
|
let reference = Storage.storage()
|
|
.reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
|
|
.rx
|
|
|
|
let data: Data // Upload data
|
|
reference.putData(data)
|
|
.subscribe(onNext: { metadata in
|
|
// Success
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
|
|
|
|
let fileURL: URL // Upload file
|
|
reference.putFile(from: fileURL)
|
|
.subscribe(onNext: { metadata in
|
|
// Success
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
```
|
|
|
|
Observe events:
|
|
```swift
|
|
let reference = Storage.storage()
|
|
.reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
|
|
.rx
|
|
|
|
let fileURL: URL // Upload file
|
|
let uploadTask = reference.putFile(from: fileURL)
|
|
|
|
// Listen for state changes
|
|
uploadTask.rx.observe(.progress)
|
|
.subscribe(onNext: { snapshot in
|
|
// Upload reported progress
|
|
let percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount)
|
|
/ Double(snapshot.progress!.totalUnitCount)
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
```
|
|
|
|
Download:
|
|
```swift
|
|
let reference = Storage.storage()
|
|
.reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
|
|
.rx
|
|
|
|
// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
|
|
reference.getData(maxSize: 1 * 1024 * 1024)
|
|
.subscribe(onNext: { data in
|
|
// Data for "images/space.jpg" is returned
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
|
|
|
|
|
|
// Create local filesystem URL
|
|
let localURL = URL(string: "path/to/image")!
|
|
|
|
// Download to the local filesystem
|
|
reference.write(toFile: localURL)
|
|
.subscribe(onNext: { data in
|
|
// Local file URL for "images/space.jpg" is returned
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
```
|
|
|
|
URL:
|
|
```swift
|
|
let reference = Storage.storage()
|
|
.reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
|
|
.rx
|
|
|
|
// Fetch the download URL
|
|
reference.downloadURL()
|
|
.subscribe(onNext: { url in
|
|
// Get the download URL for 'images/space.jpg'
|
|
}, onError: { error in
|
|
// Handle any errors
|
|
}).disposed(by: disposeBag)
|
|
```
|
|
|
|
Metadata:
|
|
```swift
|
|
let reference = Storage.storage()
|
|
.reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
|
|
.rx
|
|
|
|
// Create file metadata to update
|
|
let newMetadata = StorageMetadata()
|
|
|
|
// Update metadata properties
|
|
reference.updateMetadata(newMetadata)
|
|
.subscribe(onNext: { metadata in
|
|
// Updated metadata for 'images/space.jpg' is returned
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
|
|
|
|
// Get metadata properties
|
|
reference.getMetadata()
|
|
.subscribe(onNext: { metadata in
|
|
// Metadata now contains the metadata for 'images/space.jpg'
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
```
|
|
|
|
Delete:
|
|
```swift
|
|
let reference = Storage.storage()
|
|
.reference(forURL: "\(your_firebase_storage_bucket)/images/space.jpg")
|
|
.rx
|
|
|
|
// Delete the file
|
|
reference.delete()
|
|
.subscribe(onNext: {
|
|
// File deleted successfully
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
```
|
|
|
|
### Auth
|
|
|
|
Create:
|
|
|
|
```swift
|
|
let auth = Auth.auth()
|
|
|
|
// Create a password-based account
|
|
auth.rx.createUser(withEmail: "xxx@xxx.com", password: "1q2w3e4r")
|
|
.subscribe(onNext: { authResult in
|
|
// User signed in
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/auth/ios/password-auth
|
|
```
|
|
|
|
Sign In:
|
|
|
|
```swift
|
|
let auth = Auth.auth()
|
|
|
|
// Sign in a user with an email address and password
|
|
auth.rx.signIn(withEmail: "xxx@xxx.com", password: "1q2w3e4r")
|
|
.subscribe(onNext: { authResult in
|
|
// User signed in
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/auth/ios/password-auth
|
|
```
|
|
|
|
#### User
|
|
|
|
Update Email:
|
|
|
|
```swift
|
|
let user = Auth.auth().currentUser?
|
|
|
|
// Set a user's email address
|
|
user.rx.updateEmail(to: "xxx@xxx.com")
|
|
.subscribe(onNext: {
|
|
// Completed updating Email
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/auth/ios/manage-users
|
|
```
|
|
|
|
Delete:
|
|
|
|
```swift
|
|
let user = Auth.auth().currentUser?
|
|
|
|
// Delete a user
|
|
user.rx.delete()
|
|
.subscribe(onNext: {
|
|
// User deleted
|
|
}, onError: { error in
|
|
// Uh-oh, an error occurred!
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/auth/ios/manage-users
|
|
```
|
|
|
|
### Functions
|
|
|
|
```swift
|
|
let functions = Functions.functions()
|
|
let request = functions.httpsCallable("functionName").rx
|
|
|
|
request
|
|
.call(["parameter": "value"])
|
|
.subscribe(onNext: { result in
|
|
print("response:\(result)")
|
|
}, onError: { error in
|
|
print("error:\(error)")
|
|
}).disposed(by: disposeBag)
|
|
|
|
// https://firebase.google.com/docs/functions/callable#call_the_function
|
|
```
|
|
|
|
## License
|
|
|
|
This library belongs to _RxSwiftCommunity_.
|
|
|
|
RxFirebase is available under the MIT license. See the LICENSE file for more info.
|
|
|