【Firebase】不用錢的NoSQL資料庫?

相信大家都有聽過firebase的大名吧?它已經是APP開發者最愛的BaaS - 後端服務平臺之一,自從Google買下它之後,一直在積極的將本身的一些服務轉到上面,像是最有名的例子就是將推播服務的GCM - Google Cloud Messaging轉成FCM - Firebase Cloud Messaging,還有將Fabric關閉等…,總總的跡象都表示Google的決心。其實市面上另外還有一套叫Parse.com的資料庫,是由Facebook買下,不過由於不賺錢就關閉跟開源了。以下的Code只會寫出比較重要的部分,如果要完整的Code的話,請去github下載,感謝。

Realtime Database

建立Realtime資料庫

  • 首先要有個gmail帳號用來登入firebase console,接下來就是按影片施工,保證成功。

資料結構

  • 其實它的資料庫就是一個大的JSON檔,大家可以先在JSON Editor Online上輸入資料比較方便,雖然JSON上有Array([value])跟Object({key: value})兩種結構存在,但在Firebase上看起來是把Array也變成了有key的object了,所以直接在上面輸入時,也要輸入0跟1才可以。大家也可以試試匯入匯出的功能。
  • 另外在資料庫的網址後面加上『/.json』的話可以直接看到完整的json資料

將Firebase新增至iOS應用程式

  • 這裡會使用Xcode 10 + Firebase Framework來做測試,用CocoaPods的安裝過程就不多做說明了,主要是將AppID給Firebase資料庫知道,然後經過處理之後,會發一個『GoogleService-Info.plist』下來,將它放在iOS的專案之內,以下是新增的影片,可以參考看看,在註冊的過程中也有詳細的提示。

安裝Framework

  • 再來就是安裝Firebase/Database套件,因為我們要使用Database嘛,安裝完成後就如圖所示,但是『GoogleService-Info.plist』一定要在第一層,不然Firebase就不能動了。
pod 'Firebase/Database'

使用測試

  • 這裡主要是看看能不能動作,如果有印出資料的話,就可以進行下一步的動作。
import UIKit
import FirebaseDatabase

class ViewController: UIViewController {

    @IBOutlet var myTableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
		
	let database = Database.database().reference()    
        database.observeSingleEvent(of: .value) { (value) in
            print("value = \(value)")
        }
    }
}

Realtime Database CRUD

讀取資料

Realtime Database讀取資料的方式,可分為單次跟及時更新的,單次的話就是當下只讀取一次資料,而及時的話就是資料有更動 - FIRDataEventType的時候就會再去讀取一次。大家可以直接去資料庫改改值據,就能體會其中的差異了。

import UIKit
import FirebaseDatabase

class FIRDatabase: NSObject {
    
    public static let shard = FIRDatabase()
    public let database = Database.database().reference()
    
    private override init() { super.init() }
}

// MARK: - 主工具
extension FIRDatabase {
    
    /// 取值 (單次 / 及時)
    func childValueFor(type: RealtimeDatabaseType, withPath path: String, result: @escaping ((Any?) -> Void)) {
        
        switch type {
        case .single: childValueForSingle(withPath: path) { (value) in result(value) }
        case .realtime: childValueForRealtime(withPath: path) { (value) in result(value) }
        }
    }
}

// MARK: - 小工具
extension FIRDatabase {
    
    /// 取值 (單次)
    private func childValueForSingle(withPath path: String, result: @escaping ((Any?) -> Void)) {
        
        database.child(path).observeSingleEvent(of: .value, with: { (snapshot) in
            result(snapshot.value)
        }, withCancel: { (error) in
            result(nil)
        })
    }
    
    /// 取值 (及時)
    private func childValueForRealtime(withPath path: String, result: @escaping ((Any?) -> Void)) {
        
        database.child(path).observe(.value, with: { (snapshot) in
            result(snapshot.value)
        }, withCancel: { (error) in
            result(nil)
        })
    }
}

設定資料

  • firebase設定資料的方法也滿簡單的,不過要注意的是,一經設定之後,原資料都會『不見』喲,整個會被刪掉,很可怕的,如果原來沒有這個值也會自動補上去。
// MARK: - 小工具
extension FIRDatabase {
    
    /// 設定數據
    func setChildValue(withPath path: String, values: [String: Any], result: @escaping ((Any?) -> Void)) {

        let isOK = true
        
        database.child(path).setValue(values) { (error, database) in
            if error != nil { result(!isOK); return }
            result(isOK)
        }
    }
}

更新資料

  • firebase更新資料的方法跟設定資料差不多,如果原來沒有這個值也會自動補上去,但是一經設定之後,只會更新原有的資料。
// MARK: - 小工具
extension FIRDatabase {

    /// 更新數據
    func updateChildValue(withPath path: String, values: [String: Any], result: @escaping ((Any?) -> Void)) {
        
        let isOK = true
        
        database.child(path).updateChildValues(values) { (error, database) in
            if error != nil { result(!isOK); return }
            result(isOK)
        }
    }
}

查詢資料

  • firebase查詢數據的功能其實滿強大的,本來還以為使用上跟SQL一樣複雜,不過其實還滿單純的。
// MARK: - 小工具
extension FIRDatabase {

    /// 查詢數據
    func queryChildValue(withPath path: String, byKey key: String, value: Int, result: @escaping ((Any?) -> Void)) {
        
        database.child(path).queryOrdered(byChild: key).queryEqual(toValue: value).observe(.value, with: { (snapshot) in
            result(snapshot.value)
        }, withCancel: { error in
            result(nil)
        })
    }
}

範例程式碼下載

後記

  • Firebase對前端打字工來說,無非是一個快速上手的好工具,建議大家可以多多學學。