Firebase を使って30分でiOSのチャットアプリを作ってみる(新SDK対応版)
はじめに
本記事は以下の記事の新SDK対応版です
crossbridge-lab.hatenablog.com
BaaS の1つである Firebase の勉強がてらサンプル的なiOSのチャットアプリを作ったメモです。Firebaseの使い方はとても簡単でした。
Firebaseとは
Firebase とはチャットアプリのようなリアルタイムにデータを同期する必要があるサービスに適しているバックエンドサービスです。データはSQLではなくJSONのオブジェクトとして保存されます。Parse を使おうとした矢先に終了のお知らせが出てしまったので、何か他のサービスを使ってみようと Firebase を選んでみました。 ※使う理由としてはチャットアプリではないのですがまずは勉強に簡単なチャットアプリをということです。
アカウント登録
https://www.firebase.com からGoogleアカウントで SIGN UP すれば完了です。速い。
管理画面で新規プロジェクトを作成
ログインすると Console (管理画面)が表示されます。
この画面で新規プロジェクトを作成をクリックします。そしてプロジェクト名と国を選択してプロジェクト作成をクリックします。
SDKを導入
プロジェクトを作成したらアプリの管理画面に進むのでiOSアプリにFirebaseを追加をクリックします。もし管理画面を閉じていた場合はConsoleから作成したアプリを選択するとアプリの管理画面に進みます。
iOSアプリにFirebaseを追加をクリックすると作成するアプリのバンドルIDとApp StoreIDの入力を求められます。とりあえずバンドルIDだけ入力してアプリを追加をクリックして進みます。
アプリを追加をクリックするとGoogleServie-info.plist
というファイルがダウンロードされるので画面の説明の通りプロジェクトに追加し、続行をクリックします。
次の画面の説明の通りCocoaPodsでSDKをさくっと入れます。Firebaseには様々な機能があり、それぞれライブラリを入れることになりますが今回はデータベースを使うのでpod 'Firebase/Database'
の1行も追加します。
pod 'Firebase' pod 'Firebase/Database'
そしてAppDelegateクラスで以下のようにFirebaseのimportと初期化コードを入れればこれでFirebaseを使う準備が完了です。
import UIKit import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { FIRApp.configure() // 初期化 return true } // 以下省略
ルールを設定
デフォルトではデータベースへのアクセスには認証が必要となっています。今回はとりえあえずチャットアプリを作るということが目的なので、誰でもアクセスできるようにします。 ※本来はアクセス制限をすべきです。
アプリの管理画面の左側からDatabeseを選択します。そしてルールタブをクリックして以下のように修正します。そして公開ボタンをクリックして反映させます。公開ボタンをクリックしないと反映しないので注意しましょう。
{ "rules": { ".read": true, ".write": true } }
UIを適当に作る
UITextView と UITextField x 2 の極めてダサいシンプルなUIにします。
Outletも忘れずに。
@IBOutlet weak var textView: UITextView! @IBOutlet weak var nameTextField: UITextField! @IBOutlet weak var messageTextField: UITextField!
初期設定
var databaseRef:FIRDatabaseReference! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. databaseRef = FIRDatabase.database().reference()
データベースにはFIRDatabaseReferenceクラスを通じてアクセスします。FIRDatabase.database().reference()
でインスタンスを取得します。
データの読み込み
observeEventType
メソッドが名前の通りイベントを監視するメソッドです。ここでは.ChildAdded
を指定して子要素が追加されたときにwithBlockで与えた処理が実行されるようにしています。データに追加があると自動で呼ばれるので、更新ボタンやPull to refreshを実装する必要はありません。
snapshot
というのが追加されたデータで、そこからnameとmessageの値を取り出してTextViewに追記していきます。
databaseRef.observeEventType(.ChildAdded, withBlock: { snapshot in if let name = snapshot.value!.objectForKey("name") as? String, message = snapshot.value!.objectForKey("message") as? String { self.textView.text = "\(self.textView.text)\n\(name) : \(message)" } })
データの書き込み
送信ボタンを作るのも面倒なのでReturn入力時に送信するようにしています。childByAutoId
メソッドがランダムな名前の子要素を作るメソッドで、setValue
メソッドでデータを書き込みます。Dictionaryを作って与えています。
func textFieldShouldReturn(textField: UITextField) -> Bool{ let messageData = ["name": nameTextField.text!, "message": messageTextField.text!] databaseRef.childByAutoId().setValue(messageData) textField.resignFirstResponder() messageTextField.text = "" return true }
実際には以下のようにデータが保存されます。
完成
以上で完成です。多分、30分もかかっていないですね。ViewControllerのソースはキーボードを開いた時にTextFieldを上に持ち上げる処理などを除けば以下のように。
@IBOutlet weak var textView: UITextView! @IBOutlet weak var nameTextField: UITextField! @IBOutlet weak var messageTextField: UITextField! var databaseRef:FIRDatabaseReference! override func viewDidLoad() { super.viewDidLoad() databaseRef = FIRDatabase.database().reference() databaseRef.observeEventType(.ChildAdded, withBlock: { snapshot in if let name = snapshot.value!.objectForKey("name") as? String, message = snapshot.value!.objectForKey("message") as? String { self.textView.text = "\(self.textView.text)\n\(name) : \(message)" } }) } func textFieldShouldReturn(textField: UITextField) -> Bool{ let messageData = ["name": nameTextField.text!, "message": messageTextField.text!] databaseRef.childByAutoId().setValue(messageData) textField.resignFirstResponder() messageTextField.text = "" return true }
最後に
でもお高いんでしょ?https://firebase.google.com/pricing/ が料金プランのページです。コネクション数、ストレージの容量、転送量などで分かれています。小さなアプリ(サービス)なら無料でもいけるのでは?といった感じです。