Swiftで始めるFirebase入門

# やること
今回は入門ということでFirebaseの始め方から、簡単なデータの追加、取得、更新、削除までをやっていきます。

# 予習
・[一歩進んだMBaas，Firebaseとは？](http://gihyo.jp/dev/serial/01/firebase/0001)
・[フロントエンジニアが今話題のFirebaseについて語りたい](http://qiita.com/gonta616/items/8896bcffa04fb00b9567)
・[Firebaseの始め方](http://qiita.com/kohashi/items/43ea22f61ade45972881)

# 開発環境
Swift3
Xcode8

# 準備
## 1. Xcodeでプロジェクトファイルを作成する
今回はSingle View Applicationで名前はstartFirebaseで作成しました。
そしてハンドルIDをコピーしておきます。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/135478/e24fb9f5-b389-cd15-ae13-a71d23183023.png)


## 2. Firebaseでプロジェクトを作成する
Googleアカウントにログインした状態で、[https://firebase.google.com/](https://firebase.google.com/)にアクセス、「無料で開始」をクリック。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/135478/bee7827d-8ee8-cf2b-4f51-4e7f70f8b8ff.png)


コンソール画面に移動するので、「新規プロジェクトを作成」をクリック。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/135478/d55e29f2-c463-61bc-e4e5-36ffa13b24d8.png)


プロジェクト名を入力し、国を選んで「プロジェクトを作成」をクリック。
すると作成したプロジェクトのページにリダイレクトされます。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/135478/c4316232-b479-ab04-0250-56459c084e78.png)


## 3. iOSアプリにFirebaseを追加
「iOSアプリにFirebaseを追加」をクリック
![5-1.png](https://qiita-image-store.s3.amazonaws.com/0/135478/1731c53a-efd9-4945-94df-737238d87a29.png)


ここで先程コピーしたバンドルIDを入力して、「アプリを追加」をクリック。
※App Store ID（省略可） は空欄のままで構いません。
![6.png](https://qiita-image-store.s3.amazonaws.com/0/135478/59bbcaca-a449-aff7-e3e1-3be74915849c.png)


GoogleService-Info.plistが自動でダウンロードされますので、 Xcodeのプロジェクトにドラッグ＆ドロップで追加します。
![7.png](https://qiita-image-store.s3.amazonaws.com/0/135478/54caf7b6-1f1b-dab0-8e15-ff17b286acb2.png)
追加できたら一旦プロジェクトファイルを閉じます。

次にCocoaPodsをインストールしてイキます。
ターミナルを起動し、cdコマンドで先程作成したXcodeのプロジェクトフォルダに移動します。
![8-1.png](https://qiita-image-store.s3.amazonaws.com/0/135478/a919cd3d-a0ba-9060-5598-5c7a98ca45f9.png)



```pod init```でPodfileを作成し、```vi Podfile```でPodfileを開きます。
![9-1.png](https://qiita-image-store.s3.amazonaws.com/0/135478/a8364f28-418a-5690-cfa5-857637569fb7.png)



iで挿入モードにして```pod 'Firebase/Database'```を追記。
escで挿入モードを終了し、:wqと入力し、エンターで上書き保存。
![0-1.png](https://qiita-image-store.s3.amazonaws.com/0/135478/a92c6dbe-1279-5fbf-4718-0f146381e48e.png)



最後に```pod install```でインストール。
2016年10月16日現在の最新バージョン3.7.1になっていることを確認します。
もしバージョンが古い場合は```pod update Firebase```でアップデートしてください。
![0-2.png](https://qiita-image-store.s3.amazonaws.com/0/135478/e6a8c077-e2dc-8bcc-6d99-4f10188202f5.png)


Xcodeプロジェクトフォルダに「startFirebase.xcworkspace」が作られました。
![12.png](https://qiita-image-store.s3.amazonaws.com/0/135478/43576b04-301a-b061-a228-b0af543b2744.png)
以降「startFirebase.xcworkspace」を使って編集していきます。

## 4. 初期設定
「startFirebase.xcworkspace」を開き、AppDelegate.swiftに```import Firebase```と初期化コード```FIRApp.configure()```を追記します。
![13.png](https://qiita-image-store.s3.amazonaws.com/0/135478/2e26a906-9f40-7492-fbd2-2a3b9a039288.png)


## 5. Databaseのルールを変更
コンソールのDatabase→ルールのタブでルールを下記のように変更し、「公開」をクリック。
![14.png](https://qiita-image-store.s3.amazonaws.com/0/135478/65fd8658-77ec-0148-ffed-70b92afc3400.png)

```.json
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
```

上記の設定は全ての階層で誰でも読み込み・書き込みができるという設定になります。
実際に公開するアプリではセキュリティー上好ましくありませんが、今回はテストのためこの設定でイキます。


## 6. ビルド時の警告について
プロジェクトファイルをビルドすると<font color="red">Conflicting nullability specifier on return types, 'nullable' conflicts with existing specifier 'nonnull'</font>という警告が出ます。
またデバッグコンソールにもWARNINGが沢山出ています。
これはXcode8のバグなので次回のアップデートを待ちましょう。
![15.png](https://qiita-image-store.s3.amazonaws.com/0/135478/40fc7476-e2f3-b5ae-adf7-c0f912c2cd8a.png)

どうしても気になる場合はFIRApp.hファイルに以下の三行を追記すると警告が消えます。

```
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullability"
#pragma clang diagnostic pop
```

![16.png](https://qiita-image-store.s3.amazonaws.com/0/135478/1e6a7b8d-226c-c194-ea0c-7b1485107a64.png)

デバッグコンソールの警告は実機でビルドすると表示されなくなります。


これで準備が整いました。
次からは実際にデータを扱ってイキます。

# データの追加(setValue)
user/01にname: "Kelly"というデータを追加します。

## デモ
![add.gif](https://qiita-image-store.s3.amazonaws.com/0/135478/7dd6ec17-deda-22d5-acda-63f22423d501.gif)


## コード

```ViewController.swift
import UIKit
import Firebase

class ViewController: UIViewController {

    @IBOutlet weak var TextField: UITextField!
    
     // インスタンス変数
     var DBRef:FIRDatabaseReference!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //インスタンスを作成
        DBRef = FIRDatabase.database().reference()
    }

    @IBAction func add(_ sender: AnyObject) {
        let data = ["name": TextField.text!]
        DBRef.child("user/01").setValue(data)
    }
}
```

ちなみにデータの追加はコンソール画面から手動で追加することもできます。
![shudouadd.gif](https://qiita-image-store.s3.amazonaws.com/0/135478/ba23280a-8e78-858a-4dea-f2d34ca7ccf2.gif)


# データの取得(DataSnapshot)
先程のsetValueとDataSnapshotを使って、追加したデータを取得して画面に表示するプログラムを作ります。
追加するデータはage: 23です。

## デモ
![setvalueage2.gif](https://qiita-image-store.s3.amazonaws.com/0/135478/7bf05c38-077c-3abe-7416-1ed47fc897b0.gif)




## コード

```ViewController.swift
import UIKit
import Firebase

class ViewController: UIViewController {

    @IBOutlet weak var TextField: UITextField!
    @IBOutlet weak var displayAge: UILabel!
    
     // インスタンス変数
     var DBRef:FIRDatabaseReference!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //インスタンスを作成
        DBRef = FIRDatabase.database().reference()
    }

    @IBAction func add(_ sender: AnyObject) {
        let age: Int = Int(TextField.text!)!
        let data = ["age": age]
        DBRef.child("user/01").setValue(data)
        
        let defaultPlace = DBRef.child("user/01/age")
        defaultPlace.observe(.value) { (snap: FIRDataSnapshot) in self.displayAge.text = (snap.value! as AnyObject).description
        }
    }
}
```

今回のデモでは一番最初に追加したname: "Kelly"というデータが削除されてしまいました。
これは、<font color="red">setValueが指定した階層以下の全てを上書きする</font>ためであります。
ですので、今あるデータを残しつつ新しくデータを追加したい場合や、データの一部を変更したい場合は次に説明するupdateChildValuesを使います。

# データの更新(updateChildValues)
先程消えてしまったデータ(name: "Kelly")を追加して行きたいと思います。
Valueのみを更新することもできます。
## デモ
![update000.gif](https://qiita-image-store.s3.amazonaws.com/0/135478/eed2dc9c-f3f4-b877-bb00-f8a3e901b3d5.gif)



## コード

```ViewController.swift
import UIKit
import Firebase

class ViewController: UIViewController {

    @IBOutlet weak var TextField: UITextField!
    
     // インスタンス変数
     var DBRef:FIRDatabaseReference!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //インスタンスを作成
        DBRef = FIRDatabase.database().reference()
    }

    @IBAction func update(_ sender: AnyObject) {
        let data = ["name": TextField.text!]
        DBRef.child("user/01").updateChildValues(data)
        
    }
}
```

# データの削除(removeValue)
先程追加したname: "Kelly"を削除します。

## デモ
![remove2.gif](https://qiita-image-store.s3.amazonaws.com/0/135478/fc12d3a7-fa07-7994-382a-870a35e85f05.gif)

## コード

```ViewController.swift
import UIKit
import Firebase

class ViewController: UIViewController {

    @IBOutlet weak var TextField: UITextField!

     // インスタンス変数
     var DBRef:FIRDatabaseReference!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //インスタンスを作成
        DBRef = FIRDatabase.database().reference()
    }

    @IBAction func update(_ sender: AnyObject) {
        let data = ["name": TextField.text!]
        DBRef.child("user/01").updateChildValues(data)
    }
    
    @IBAction func remove(_ sender: AnyObject) {
        DBRef.child("user/01/name").removeValue()
    }
}
```


以上、Swiftで始めるFirebase入門でした。