Firebase: Quick Start Guide

firebase

Firebase Console

It all starts at the Firebase console

Steps

  1. Add a new project
  2. Add Firebase to your iOS app.
    1. Add the iOS bundler from your Xcode app. Register the app.
    2. 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.
  3. 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
  4. 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)
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s