Firebase Console
It all starts at the Firebase console
Steps
- Add a new project
- Add Firebase to your iOS app.
- Add the iOS bundler from your Xcode app. Register the app.
- Download config file (GoogleService-Info.plist) Move the GoogleService-Info.plist file you just downloaded into the root of your Xcode project and add it to all targets.
- Adding Authentication: Authenticate and manage users from a variety of providers without server-side code.
- Setup sign-in method. Some options include Email / Password, Phone, Google……
- Also included as part of Email / Password Authentication is a Email link (passwordless sign-in) to enable
- Database Options:
- Cloud Firestore (Beta)
- Realtime Database: default is start in locked mode
Default values where the database is in locked mode, no reading or writing
{ "rules": { ".read": false, ".write": false } }
To allow for authentication
{ "rules": { ".read": "auth != null", ".write": "auth != null" } }
Authenticate with Firebase using Password-Based Accounts on iOS
Navigate over to your project folder and run pod init
This will create a CocoaPods Podfile. Open the Podfile and add the following pod:
pod 'Firebase/Auth'
Now run pod install
The following pods will be installed:
Installing Firebase (4.11.0)
Installing FirebaseAnalytics (4.1.0)
Installing FirebaseAuth (4.5.0)
Installing FirebaseCore (4.0.18)
Installing FirebaseInstanceID (2.0.10)
Installing GTMSessionFetcher (1.1.15)
Installing GoogleToolboxForMac (2.1.3)
Installing nanopb (0.3.8)
Close your Xcode project and now navigate to your project folder and open YourProjectName.xcworkspace. This will now be the project you need to work in as the workspace now consists of your installed Pods and required folders.
Navigate to the AppDelegate.swift and add the following:
import Firebase
//
//
//
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Use Firebase library to configure APIs
FirebaseApp.configure()
return true
}
testCreateUser
func testCreateUser() {
let exp = XCTestExpectation.init(description: "user created")
// password must be 6 characters long or more
let testEmail = "testuser1@test.com"
Auth.auth().createUser(withEmail: testEmail, password: "123456") { (user, error) in
if let error = error {
XCTFail("create user error: \(error.localizedDescription)")
}
guard let user = user else { fatalError("user is nil") }
if let email = user.email {
exp.fulfill()
XCTAssertEqual(email, testEmail)
} else {
XCTFail("email is nil")
}
}
wait(for: [exp], timeout: 3.0)
}
Add Firebase Realtime Database to your app
Add the following pods
pod 'Firebase/Core'
pod 'Firebase/Database'
The following pods will be added after running pod install
Installing Firebase 4.11.0
Installing FirebaseDatabase (4.1.5)
Installing leveldb-library (1.20)
Creating a reference to the database
var ref: DatabaseReference!
ref = Database.database().reference()
Read and Write Data on iOS
Writing data to the Database
testDBAddPost
func testDBAddPost() {
let exp = XCTestExpectation.init(description: "added post to database")
// Getting the database reference
let dbRef = Database.database().reference()
let key = dbRef.child("posts").childByAutoId().key
let post = ["userId" : "12345",
"created" : "\(Date().timeIntervalSince1970)",
"author" : "Sally",
"email" : "sally@sally.com",
"mediaType" : "text",
"title" : "Great Festival",
"body" : "Best festival ever."]
let childUpdates = ["/posts/\(key)": post]
dbRef.updateChildValues(childUpdates) { (error, dbRef) in
if let error = error {
XCTFail("post failed with error: \(error.localizedDescription)")
} else {
exp.fulfill()
XCTAssertNotNil(dbRef)
}
}
wait(for: [exp], timeout: 3.0)
}
Reading data from the Database
To read data at a path and listen for changes, use the observeEventType:withBlock orobserveSingleEventOfType:withBlock methods of FIRDatabaseReference to observe FIRDataEventTypeValue events.
Reads all Posts
testDBFetchAllPosts
func testDBFetchAllPosts() {
let exp = XCTestExpectation.init(description: "fetched all posts from database")
let dbRef = Database.database().reference()
dbRef.child("posts").observe(.value, with: { (snapshot) in
if let dict = snapshot.value as? [String : Any] {
exp.fulfill()
XCTAssertEqual(dict.count, 2)
} else {
XCTFail("dict is nil")
}
}) { (error) in
XCTFail("fetch data error: \(error.localizedDescription)")
}
wait(for: [exp], timeout: 3.0)
}
Query for a User’s Posts
testQueryUserPosts
func testQueryUserPosts() {
let exp = XCTestExpectation.init(description: "fetched data from database")
let dbRef = Database.database().reference()
let query = dbRef.child("posts").queryOrdered(byChild: "userId")
.queryEqual(toValue: "np9VFlQMkAWOAbMQK2e6dqOFpLv2")
query.observe(.value, with: { (snapshot) in
if let dict = snapshot.value as? [String : Any] {
exp.fulfill()
XCTAssertEqual(dict.count, 1)
} else {
XCTFail("dict is nil")
}
}) { (error) in
XCTFail("fetch data error: \(error.localizedDescription)")
}
wait(for: [exp], timeout: 3.0)
}
Deleting from the Firebase Realtime Database
func testDeletePost() {
let exp = XCTestExpectation.init(description: "post was deleted")
let dbRef = Database.database().reference()
let postToDeleteRef = dbRef.child("posts/-LDoErqkDrtX48NfFA0b")
postToDeleteRef.removeValue { (error, dbRef) in
if let error = error {
XCTFail("delete post error: \(error.localizedDescription)")
} else {
exp.fulfill()
XCTAssert(true, "post was deleted")
}
}
wait(for: [exp], timeout: 3.0)
}
Firebase Storage
Default security rules for Storage
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Add Cloud Storage to your app
pod 'Firebase/Core'
pod 'Firebase/Storage'
Now the following will be installed
Installing Firebase 4.11.0
Installing FirebaseStorage (2.1.3)
Getting a reference to the storage service:
// gets root reference from Storage
let storageRef = Storage.storage().reference()
Adding an image to Firebase Storage
testStorageUploadImage
func testStorageUploadImage() {
let exp = XCTestExpectation.init(description: "added image to storage")
// get image data
let imageURLString = "https://www.gizmochina.com/wp-content/uploads/2018/02/WWDC-2018.jpg"
let imageURL = URL(string: imageURLString)!
let imageData = try! Data.init(contentsOf: imageURL)
// gets root reference from Storage
let storageRef = Storage.storage().reference()
// Create a reference to the file you want to upload
let uploadImageRef = storageRef.child("images/\(Date().timeIntervalSince1970)")
// Create the file metadata
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
// Upload the file to the path "images/someImaage.jpg"
let _ = uploadImageRef.putData(imageData, metadata: metadata) { (storageMetadata, error) in
if let error = error {
XCTFail("upload image error: \(error.localizedDescription)")
} else if let storageMetadata = storageMetadata {
if let downloadURLs = storageMetadata.downloadURLs {
exp.fulfill()
XCTAssertGreaterThan(downloadURLs.count, 0)
}
}
}
wait(for: [exp], timeout: 3.0)
}
Downloading an image from Storage
testStorageDownloadImage
func testStorageDownloadImage() {
let exp = XCTestExpectation.init(description: "image was downloaded for post using postId")
// gets root reference from Storage
let storageRef = Storage.storage().reference()
// Create a reference to the file you want to upload
let downloadImageRef = storageRef.child("images/1527780453.37331")
// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
downloadImageRef.getData(maxSize: 1 * 1024 * 1024) { (data, error) in
if let error = error {
XCTFail("download image error: \(error.localizedDescription)")
} else if let data = data {
let image = UIImage.init(data: data)
exp.fulfill()
XCTAssertNotNil(image)
}
}
wait(for: [exp], timeout: 3.0)
}
Deleting an image from Firebase Storage
testStorageDeleteImage
func testStorageDeleteImage() {
let exp = XCTestExpectation.init(description: "image was deleted from storage")
// gets root reference from Storage
let storageRef = Storage.storage().reference()
// Create a reference to the file you want to upload
let downloadImageRef = storageRef.child("images/1527779596.7369")
downloadImageRef.delete { (error) in
if let error = error {
XCTFail("delete error: \(error.localizedDescription)")
} else {
exp.fulfill()
XCTAssert(true, "image deleted")
}
}
wait(for: [exp], timeout: 3.0)
}