ちろる

理系大学生が自由気ままに

iOSでFirebase入門 その2

今回やること

  1. データの読み込み
  2. データの書き込み
  3. 実装

メモ帳みたいな記事なので悪しからず...

読み込みと書き込みで共通のやるべきこと

まず、以下がインストールされていることを確認。

pod 'Firebase/Core'
pod 'Firebase/Database'
pod 'SwiftyJSON'

RealTime DatabaseとCloud Firestoreの2種類があるが、ここではRealTimeDatabaseを使う。コンソール(Webサイトのやつ)からRealtime Databaseのルールを開き、writeとreadの権限をtrueにする。

次はXcodeのプロジェクト側。データベースへの参照を定義する。

var ref: DatabaseReference!
ref = Database.database().reference()

データの読み込み

observeを使うことでデータベースにアクセスできる。observeメソッドはデータベースに変更がある度に自動的に呼び出される。引数によって、変更の種類を選択できる。observeの他にobserveSingleEventというメソッドがあり、こっちは一度だけ実行されるメソッド。結果はsnapShotに格納される。

var username: [String]

override func viewDidLoad() {
  super.viewDidLoad()
        
  ref = Database.database().reference()
  let postRef = ref.child("users")
        
  postRef.observe(.value) { (snapShot) in
    let json = JSON(snapShot.value as? [String : AnyObject] ?? [:])
  
    self.username = []
    for (key, val) in json.dictionaryValue {
      self.username.append(json[key]["username"].stringValue)
    }
  } 
}

データの書き込み

Firebase Realtime DatabaseではJsonオブジェクトで保存される。Json連想配列のようなもの。

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "contacts": { "ghopper": true },
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}


データベースにデータを保存する為のメソッド一覧。(公式からの引用)

メソッド 一般的な使用例
setValue users// など、定義済みのパスへのデータの書き込みや、データの置換を行います。
childByAutoId データのリストに追加します。childByAutoId を呼び出すたびに、user-posts// のような一意の識別子としても使用できる一意のキーが生成されます。
updateChildValues データのすべてを置換することなく、定義済みのパスのキーの一部を更新します。
runTransactionBlock 同時更新によって破損する可能性がある複合データを更新します。

以下のようにすることで、データベースにデータが追加されます。

let data = ["username": "jon", "message": "hello"]
let uid = "001"
ref.child("users").child(uid).setValue(data)
let data = ["username": "Albert"]
let uid = "001"

とし、ユーザー名前だけを変更したい場合、setValueだと前回追加した際に記録されている"message"が消えてしまいます。これはsetValueはchildで指定した階層以下全てを書き換えるためです。他の値を残したいまま、更新したい場合はupdateChildvaluesを用います。


childByAutoIdは自動的にIDを割り振ってくれます。

let data = ["username": "bob","message":"good bye"]
ref.child("chat").childByAutoId().setValue(data)

実装

class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var ref: DatabaseReference!
    var username: [String] = []
    

    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.dataSource = self
        tableView.delegate = self
        
        ref = Database.database().reference()
        let postRef = ref.child("users")
        
        postRef.observe(.value) { (snapShot) in
            let json = JSON(snapShot.value as? [String : AnyObject] ?? [:])
            if json.count == 0 { return }

            self.username = []
            for (key, val) in json.dictionaryValue {
                self.username.append(json[key]["username"].stringValue)
            }
            self.tableView.reloadData()
        }
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.username.count
    }
    
    func numberOfSections(in tableView: UITableView) -> Int { // sectionの数を決める
        return 1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "firebase_cell", for: indexPath)
        cell.textLabel?.text = self.username[indexPath.row]
        return cell
    }
}

class AddDataViewController: UIViewController, UITextFieldDelegate{
    
    @IBOutlet weak var username_textField: UITextField!
    @IBOutlet weak var message_textField: UITextField!
    
    var ref: DatabaseReference!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        ref = Database.database().reference()
        username_textField.delegate = self
        message_textField.delegate = self
    }
    
    @IBAction func sendData(_ sender: Any) {
        let data = ["username": username_textField.text!,"message":message_textField.text!]
        ref.child("users").childByAutoId().setValue(data)
        performSegue(withIdentifier: "toTableView",sender: nil)
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
}

参考
qiita.com
qiita.com
qiita.com
blog.all-in.xyz
qiita.com