Firebase (iOS) : Firebaseデータベースへ接続とDatabaseルール

スポンサーリンク

ユーザが作成できて、ようやくここまで来たという感じですが、あとはデータベースに接続して、ユーザ固有のデータの出し入れができれば、クラウドアプリとして扱うことができるようになると思います。(必ずしもTwitterやFacebook、メール等で認証を必要とするユーザを作らねばならないというわけではなく、アプリのタイプによっては、匿名ログインのユーザでいい場合もあるかもしれません。ただ、iPhoneで作ったデータをiPadでも同じように使いたい場合やアプリを削除して再インストールした場合でも同じユーザにアクセスしたい場合は認証を使うことになると思います。)

Firebaseのデータベースは、一見むむむな感じです。JSONなんですね。SQLなんかも使わない感じか。。慣れないと最初は扱いにくく感じるかもしれませんね。ただ、リアルタイムなので、Firebaseにつないでいるデバイスは、瞬時にデータが書きかわるような動きをします。たとえば、iPhoneとiPadで同じユーザでログインしている状態で、iPhone上でデータを書き換えると、その瞬間にiPadのデータも書き換わります。簡単にこういう仕組みを組み込めるというのは、Firebaseのとても魅力的な部分です。

コンソールで「Database」を開くと「デフォルトのセキュリティ ルールではユーザーの認証が必要です」と書かれています。認証したユーザでないとデータベースが扱えないということでしょう。ただ、単純に認証を済ませただけだと、作成したデータは他のユーザに見えてしまうようなデータが作成されてしまいます。このセキュリティルールというのが最初よくわからん部分だと思いますので、その辺からMEMOしておきます。

00


Firebaseデータベースの「ルール」

セキュリティルールの設定ってことですね。コンソールから「Database」を開き、「ルール」を開きます。

「自分のデータは自分だけに読み書きでき(usersディレクトリ)、アプリユーザ全員に見えるデータはそれはそれで用意したい(dataディレクトリ)」といった場合のデータの持たせ方をしていきたいと思います。このデータの持たせ方やルール設定の書き方も人それぞれだと思いますが、僕なりの書き方ではこんな感じにしてみました。(注記:この構造は、あくまでも一例です。この形でなければならないわけではなく、ルールとデータベースの構造でもっと様々な構造を構築することができるでしょう

{
  "rules": {
    ".read": false,
    ".write": false,
    "data": {
      ".read": true,
      ".write": false,
    },
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}

 このルール自体もJSONの形になっていますが、トップにある「rules」の設定がそれ以下の子ノードたちに継承されていき、子ノードで設定したルールで上書きするような感じのようです。まず、トップですべての読み書きをfalseにして、それ以下に「data」と「users」を作ります(任意のディレクトリ名です)。この階層構造は、この後に作る実際のデータベースの構造に相対しています。「data」以下は、読むことはできるが書き込みはできないようにしてあります。ここにアプリの様々な共有データをいれておく感じにしようと思います。そして、「users」以下の設定がミソですね。「$uid」という変数部分は、Firebase上に作成されたユーザのuidを指します(uidは、「Authentication」ページでもコピペできるようになっています)。つまり、usersディレクトリ以下に配置した uid の文字列の階層以下の読み書きの設定ができるようになります。「$uid === auth.uid」というのが、そのuidが実際に認証したユーザのuidと一致している場合に true となり、読み込みも書き込みも可能になるということです。ひとことで書くと「ユーザID階層の個別データはそのユーザでのみ読み書き可能」という設定です。

ま、おまじないのように「ルール」にこれを書いておいて、次にデータベースをどう作っていくかです。

データベースにデータを入れてみる

こんな感じ↓に、テーブルビューにFirebaseのデータがそのままリアルタイムに表示されるようなものを作ってみます。この動画にあるように、アプリ内でアイテムを作成すると即座にコンソールのデータベースにも反映されているのがわかると思います。削除も同様です。またコンソール側でアイテムを削除した場合でも、アプリのテーブルビューは反応してリストからアイテムが削除されます。

Firebase リアルタイムデータベース from mushikago on Vimeo.

ナビゲーションコントローラにビューを配置し、左ボタン「Auth」は、認証画面に遷移するようにしました。認証については、以下のMEMOを。

Firebase (iOS) : FacebookログインとTwitterログインを使ってFirebaseでユーザ認証を行う
FacebookログインやTwitterログインで取得したアクセストークン(Twitterでは、ログインセッションのTwitter認証トーク...

アイテムを追加する「+」は、簡易的にダイアログ内で文字を入力できるようにしました。このダイアログの作り方は、以下のMEMOを。

Xcode : テキストフィールド付きアラート
4ヶ月ほど、黙々と研究しておりました。A/BテスティングやらFirebaseやらを調べておりました。ということで、そろそろ、このブログ(MU...

テーブルビューに適用するカスタムクラスを用意します。

01

「UITableViewController」を継承させて、「FirebaseDataTableViewController(任意)」という名前で作成します。

02

ストーリーボードはこんな感じになりました。

03

cellのidentifierだけ「cell」と名付けておきます。

04

これであとは、FirebaseDataTableViewController.swiftを以下のように書けば動画のように動くようになります。コード内の簡単な説明だけ、コードの後でMEMOしておきます。

source code by gist.

テーブルビューコントローラクラスの初期コードに対して何を追加したかは、こちらのリビジョンにあります。

GitHub is where people build software. More than 22 million people use GitHub to discover, fork, and contribute to over 62 million projects.

observeData()というカスタム関数内にある

self.iThisRef = iRootRef.child(self.kUserPath).child(user.uid).child(self.kDocumentsPath)

というところですがこれはデータベースの

ルート
 - user
  - 認証した user の uid
   - documents

を参照するように変数を使って書いてあります。この .child(user.uid) 以下が前述したルールによって、このアプリで認証したユーザだけがアクセスできるディレクトリとなっています。「documents」にアプリで使ういろいろな情報を保管していく、といった具合です。documents以外のディレクトリを作って、userに関する情報なども入れたりしてもいいですね。この FIRDatabaseReference というパスがJSONツリーのどこを参照するかです。それに対して、observe(監視)してあげれば、それ以降、リアルタイムにデータベースと繋がってくれるという感じです。

「+」ボタンを押した時に、addItemButtonAction が呼ばれますが、ここの

let newChild = self.iThisRef?.childByAutoId()
newChild?.setValue(_data)

で新しいデータをdocuments内に作成しています。この際に使っている「.childByAutoId()」もミソですね。ランダムな文字列で子ノードを作成し、その中に _data で作成したキー/値 のデータを入れています。

特筆すべきところはこのくらいで、あとは非常にシンプルにテーブルビューに対してFirebaseのディレクトリ参照を行えていると思います。

dataディレクトリについて

上記の動画では、dataディレクトリ部分には触れてなかったのですが、下記のMEMOの例でdataディレクトリにGoogleドキュメントのデータを読み込むことをやってます。

Google ドキュメントのスプレッドシートのデータを変換して Firebase に読み込む
Firebaseのデータベースのことについてはまだ何も書いていないのですが、その先でFirebaseにデータを持ってくる方法としてどういう流...

また、こうしたデータの中から部分的にデータを抽出したり、並び順を変えて取得したりするには、以下のように「queryOrdered」「queryStarting」「queryEnding」が使えます。また、observeのように監視し続ける必要がなく一度だけ読み込みたいような場合は、「observeSingleEvent」が使えると思います。コードの例としてこんな感じです。

myRef?.queryOrdered(byChild: "lat").queryStarting(atValue: _latStart).queryEnding(atValue: _latEnd).observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot:FIRDataSnapshot) in

というわけで

このくらいがFirebaseデータベースの基本的な部分です。FirebaseのMEMOについてはおおよそこのくらいが基本的な部分だと思います。今後も、Firebase関係のMEMOについては、firebaseタグ をつけると同時に以下のページにまとめておきますのでご参考に。

Firebase / Fabric 関連
Firebase / Fabric : 関連MEMOまとめ(随時更新) FirebaseやFabric関連について長い期間かけていくつかのM...