【Swift3】Firebaseの読み書き

#　Swift3でFirebaseを扱う方法

個人的なプログラムメモですのでご了承ください。
もし、簡易的なチャットなどをFirebaseで行うのであれば参考になるかも...

##まずはFirebaseを扱えるようにしよう

FirebaseのサイトURL
[リンク](https://firebase.google.com/）

GoogleアカウントでログインしてFirebaseに登録。
特に困ることはないだろう。

右上に「コンソールへ移動」があるので、押してプジェクト一覧へ

![スクリーンショット 2017-11-27 18.59.26.png](https://qiita-image-store.s3.amazonaws.com/0/211848/a64e93c4-50ca-a401-14ad-4fc1730170c4.png)

こんな感じの画面でとりあえず置いておいて、Xcodeの準備を進めよう。

#Xcodeの準備

今回はサンプル用に簡単な読み書きを作りたいと思うので「singleViewApp」を選択作成。

ここで情報を一つ、メモっていてほしい。

![スクリーンショット 2017-11-27 19.31.54.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/adaa2c5e-fa3d-1014-b3bc-c06b2009fc1b.jpeg)




プロジェクトを作成したら一旦Xcodeは全て終了させる。

「cocoapods」を使ってFirebaseに必要なAPIをダウンロードを行う。
google先生に頼んで「cocoapods インストール」で検索してインストール。

...と言いたいところだが、私も初心者。
投げやりではなく、しっかりと書いていく。

##cocoapodsの導入
まずは、MACのターミナルを開く。
command+スペースで検索バーが出るので「ターミナル」と入力すると出てくるはずだ。
（出ない人はググってね。）

![スクリーンショット 2017-11-27 19.11.43.png](https://qiita-image-store.s3.amazonaws.com/0/211848/b57b5a3d-7356-8443-78eb-6f7db4346139.png)

もちろん、ダウンロードを行いたいのでインターネットには接続できる環境で...

![nodule_kk — -bash — 80×24.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/ea255f92-09c4-c135-d658-209170c245a8.jpeg)
（ぼかしの部分はご自身のPC情報が出ているかと思いますのでお気になさらず。）

この画面で以下のコードを実行

```sudo gem install cocoapods
```
文字の間は半角スペースを入れてください。
鍵マークが付いて、PCのパスワードを求めらるので入力。
カーソルが進まなくて不安かもしれないが、しっかり入力されているので注意。

![aa.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/875242e6-b256-c429-bdf8-20d3dc2d4c3d.jpeg)
初めてのインストールだと時間がかかり、もっといろんな情報が出るかと思います。
気長に待ちましょう。

##Firebase APIの導入
ここでやっとFirebaseの導入を行います。
放置していたFirebaseのサイトへ行き、新しいプロジェクトを作成しよう。

![スクリーンショット 2017-11-27 19.26.51.png](https://qiita-image-store.s3.amazonaws.com/0/211848/2f179988-1b69-b75b-21d4-fe3ed40b8bda.png)

プロジェクト名はご自身でわかりやすいものをつけてください。
Xcodeで作成したプロジェクト名と同一だと分かりやすいかもしれません。
地域は日本。

![スクリーンショット 2017-11-27 19.29.20.png](https://qiita-image-store.s3.amazonaws.com/0/211848/4b300024-3506-25b1-a85c-8ed362147c64.png)

こんな画面が出るので迷わず「iOS」を選択。

![スクリーンショット 2017-11-27 19.34.03.png](https://qiita-image-store.s3.amazonaws.com/0/211848/df72f651-5108-e084-ecb4-dedb377cf458.png)

ここで、メモをしてもらった「Bundle Identifier」の文字列を入力。

![スクリーンショット 2017-11-27 19.31.54.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/adaa2c5e-fa3d-1014-b3bc-c06b2009fc1b.jpeg)
コレのことだよ。

ニックネームやアップルストアIDなどは省略できるのでココでは触れない。

![スクリーンショット 2017-11-27 19.37.21.png](https://qiita-image-store.s3.amazonaws.com/0/211848/3db35ba5-f648-2235-a74b-19b00322e2d2.png)

「GoogleService-Info.plist」をダウンロード。
Xcodeに配置しろと言われるが、とりあえず保存してまだプロジェクトには加えない。

![スクリーンショット 2017-11-27 19.40.05.png](https://qiita-image-store.s3.amazonaws.com/0/211848/0b85e513-6e12-5201-c691-1c096be7739e.png)

とりあえず、そのまま続行。

![スクリーンショット 2017-11-27 20.15.12.png](https://qiita-image-store.s3.amazonaws.com/0/211848/52cf5f83-f796-d0ac-768c-51f19620007b.png)

このコードは後々書くので覚えておこう。

すると、Firebaseプロジェクトが作成される。

###Firebaseの権限を書き換える

![スクリーンショット 2017-11-27 20.20.19.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/c21810de-ccae-ead9-00c3-0fc4576d4dd2.jpeg)

データベースを選択。

![スクリーンショット 2017-11-27 20.20.40.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/55cb2986-6371-e5d7-aef3-46c8c59e2dbb.jpeg)

リアルタイムデータベースを選択。
**絶対に間違えてはいけない！！**

![スクリーンショット 2017-11-27 20.20.55.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/561cefff-b114-6459-5847-c143d3c3fb78.jpeg)

ルールを選択。
こんなコードが書かれているはずだ。

![スクリーンショット 2017-11-27 20.21.25.png](https://qiita-image-store.s3.amazonaws.com/0/211848/b4cda430-044f-40d2-4c6a-b2ff053c2967.png)

こう書き変える。
（セキュリティは無いに等しい状態なのであくまでもテスト用）

![スクリーンショット 2017-11-27 20.28.15.png](https://qiita-image-store.s3.amazonaws.com/0/211848/ec4f1458-02a4-77b6-34c2-65b1e98a68a2.png)

```    
".read": true,
".write": true
```

###プロジェクトにFirebaseを導入
ターミナルを使って、Firebaseを導入。
この際、前述した「cocoapods」がインストールされていないとエラーになるので注意。

このファイルはプロジェクトのフォルダ階層で実行しないといけないので、
まずは、ターミナル上でフォルダ位置をプロジェクトへ移動させる。

ターミナル上で...（cdのあとは半角スペースがいる）
```cd フォルダの階層```
を入力するのだが、cdの後にフォルダをドラッグ&ドロップすることでフォルダ階層が取得できる。

![スクリーンショット 2017-11-27 19.46.32.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/e9f42783-c559-fa96-5758-ed193c1282dd.jpeg)

すると、プロジェクトの階層へ移動できる。

この状態でFirebaseで支持されていたコマンド１を実行。

```pod init```

するとPodfileがプロジェクトのフォルダに作成される。

![スクリーンショット 2017-11-27 19.53.08.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/830b7f75-3866-ef72-f770-2b2843cb750e.jpeg)

開いてみよう。

![スクリーンショット 2017-11-27 19.53.43.png](https://qiita-image-store.s3.amazonaws.com/0/211848/a67ac2c0-2471-deea-b415-c74d87f3badc.png)

テキストエディタでそれぞれ開いてもらうと、内容はこんな感じになっているはずだ。

ここに記載する内容はFirebaseが支持したものとは違う内容を入力する。

![スクリーンショット 2017-11-27 19.55.10.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/7cd4dc1b-6fa4-649c-20e2-16062e1cde13.jpeg)

```
pod 'Firebase/Database'
pod 'SwiftyJSON'
pod 'Firebase/Auth'
```

SwiftyJSONはFirebaseのデータを扱いやすくするためのAPI。
保存してもらい、三度ターミナルへ。

```pod install```

を実行し、インストールを行う。

すると「プロジェクト名.xcworkspace」が作成されているはずだ。

![スクリーンショット 2017-11-27 19.59.35.jpg](https://qiita-image-store.s3.amazonaws.com/0/211848/c167aa90-546f-5850-0ff8-61e6e4b344f2.jpeg)

これをダブルクリックで実行し、Xcodeが起動される。

ここで、ダウンロードを行った「GoogleService-Info.plist」を配置する。

その際、ポップアップウィンドが出たら、このようにチェックをつけてほしい。

![スクリーンショット 2017-11-27 20.02.53.png](https://qiita-image-store.s3.amazonaws.com/0/211848/a923a434-2d5d-a9e8-e1cf-7bb93f8948f5.png)

これで、ファイルがプロジェクトにコピーされる。

長かったがFirebase APIの導入は終了。

#実際にコードを書いてゆく
ご自身のやりたいことに合わせて、レイアウトなどは変更しても大丈夫です。
Firebaseの書き込み、読み込みの部分だけを抑えてもらえれば問題ないかと...

**コードを書く前に「command+B」でビルドしておくこと。**

![スクリーンショット 2017-11-27 20.10.27.png](https://qiita-image-store.s3.amazonaws.com/0/211848/05c75bd9-05f7-8fee-0857-790acd296c1a.png)

クッソ簡単なビューを作成。
メッセージ入力(送信する内容)のTextField
入力されたメッセージを送信するButton
データーを取得するTextView

ではコードを書いていこう。

##Firebaseのコード
まずは、導入したAPIを導入。

```Swift:AppDelegate.swift
import UIKit
import Firebase //Firebaseを扱えるようにインポート

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        FirebaseApp.configure() //Firebase「初期コードを追加」で記載されていた内容。
        return true
    }
```

追加部分は...
```
import Firebase
FirebaseApp.configure()
```

###次は簡単なUI部分のコード

```Swift:ViewController.swift
import UIKit

import Firebase
import SwiftyJSON
import FirebaseAuth

class ViewController: UIViewController {
    
    //Firebase
    var ref:DatabaseReference!
    
    //取得した内容を表示するTextView
    @IBOutlet weak var msgTextView: UITextView!
    
    //送信するメッセージ入力欄 TextField
    @IBOutlet weak var msgTextField: UITextField!
    
    //TextFieldの内容をFirebaseに登録する送信ボタン
    @IBAction func postButton(_ sender: UIButton) {

        //childByAutoIdはランダムな文字列でIDを付与してくれる。
        self.ref.child("data").childByAutoId().setValue(["msg": msgTextField.text])
        
        //データが欲しい childAdded
        ref.child("data").observe(.value , with: { (snapshot: DataSnapshot) in
            
            //JSON形式でもらいたい　オートIDから
            let getjson = JSON(snapshot.value as? [String : AnyObject] ?? [:])
            
            //データが0件の場合何もしない
            if getjson.count == 0 { return }
            
            //TextViewを空に
            self.msgTextView.text = ""
            
            //keyから辞書型、"msg"の内容を代入 "\n"は改行
            for (key, val) in getjson.dictionaryValue {

                //key情報と入力した文字を表示する
                self.msgTextView.text = self.msgTextView.text + "key:\(key)\nmsg:\(getjson[key]["msg"].stringValue)\n"
            }
        })
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        ref = Database.database().reference()

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
```

##何をしているかというと...
###①Firebaseを扱いたいのでデータベースでデータの読み書きを行うインスタンスを宣言

```Swift:
var ref:DatabaseReference!
```

###②viewDidLoadでFirebaseDatabaseのルートを獲得

```Swift:
ref = Database.database().reference()
```
###③入力した文字をFirebaseに書き込む
ここでは入力フォームTextFieldの内容をセット。

```Swift:
self.ref.child("data").childByAutoId().setValue(["msg": msgTextField.text])
```
どのようなデータとして入っているか見てみよう。

**Firebase上のデータ**
![スクリーンショット 2017-11-27 21.55.31.png](https://qiita-image-store.s3.amazonaws.com/0/211848/7fcb3cf8-aa93-c041-6084-c6da6812f5f3.png)

```data - オートID - msg:実際の内容```
となっている。

なのでこう変えると...

```Swift:
self.ref.child("hoge").child("hoge1").child("hoge2").childByAutoId().setValue(["msg": msgTextField.text])
```

**Firebase上のデータ**
![スクリーンショット 2017-11-27 21.59.24.png](https://qiita-image-store.s3.amazonaws.com/0/211848/0d78586a-4240-df61-dcd5-2bcc63212be4.png)

このような階層になる。
ユーザーごとに管理したり、様々な情報がある場合はこの部分をうまくやりくりしよう。


###④Firebase上のデータを取得

```Swift:
ref.child("data").observe(.value , with: { (snapshot: DataSnapshot) in
//内容
})
```
snapshotにデータあるのでやりくりをする。

####④-1
ここでFirebaseの情報をJSON形式で受け取る。

```Swift:
let getjson = JSON(snapshot.value as? [String : AnyObject] ?? [:])
```



####④-2
JSON形式のデータKeyとValueで分ける。
その後、TextViewにkey情報で引っ張ってきた"msg"の内容を代入。

```Swift:
//keyから辞書型、"msg"の内容を代入 "\n"は改行
for (key, val) in getjson.dictionaryValue {

    //key情報と入力した文字を表示する
    self.msgTextView.text = self.msgTextView.text + "key:\(key)\nmsg:\(getjson[key]["msg"].stringValue)\n"
}
```


####シミュレーター上ではこんな感じ
![スクリーンショット 2017-11-27 22.12.26.png](https://qiita-image-store.s3.amazonaws.com/0/211848/da092fd7-ceb1-e114-fe26-c3c5f667d46a.png)

#おわり
Swift初心者の自分用メモなので、間違いやもっと簡単にデータが取れる方法があるかもしれません。
Swift3での環境なのでご注意ください。