最初に
この記事は、SwiftでFirebaseのデータ構造を、
モデルクラスで管理するためにObjectMapperを利用して、
更に少しアレンジを加えると使いやすくなるのを共有する記事です。
記載時(2016/12/17)のバージョンは下記の通りです。
対象 | バージョン |
---|---|
Swift | 3.0.1 |
ObjectMapper | 2.2.2 |
Firebase/Database | 3.9.0 |
FirebaseとObjectMapperの導入方法
Firebase
https://firebase.google.com/docs/database/?hl=ja
公式のチュートリアルが一番わかりやすいので、
Firebase databaseが初めての方は データの取得まで終わらせてください。
ObjectMapper
下記のページで導入方法が記載されています。
https://github.com/Hearst-DD/ObjectMapper#installation
pod 'ObjectMapper', '~> 2.2'
github "Hearst-DD/ObjectMapper" ~> 2.2
実装
Firebaseのチュートリアルを終えた方はお気付きだと思いますが、モデルクラス化の方法までは記載されていません。
なので、Firebase Realtime Databaseを使ってる方々はどのように使っているんだろう?と思い調べると、様々なやり方がありますが、
色々試した結果、僕の中ではObjectMapperに落ち着きました。
{
"Articles": {
"1" : {
"title": "一番目の記事"
},
"2" : {
"title": "二番目の記事"
},
}
}
class Article: Mappable {
var id: String?
var title: String?
required init?(map Map: Map){
}
func mapping(map: Map) {
id <- map["id"]
title <- map["title"]
}
}
上記のJSONを ArticleClass
に ObjectMapper
を用いて、mappingする時は、下記の処理を行うと思います。
let articleId = "1"
FIRDatabase.database().reference().child("articles").child(articleId).observeSingleEvent(of: .value, with: { (snapshot) in
if let json = snapshot.value as? [String : AnyObject] {
let article = Mapper<Article>().map(JSON: json)
}
}
しかし、そのままでは id
は value
ではなく key
なのでmappingされず、nil
のままです。
let articleId = "1"
FIRDatabase.database().reference().child("articles").child(articleId).observeSingleEvent(of: .value, with: { (snapshot) in
if let json = snapshot.value as? [String : AnyObject] {
let article = Mapper<Article>().map(JSON: json)
article.id = articleId // 微妙・・><
}
}
上記の様に実装してもいいのですが、
これだと毎回id
を設定するのが面倒なので・・
import ObjectMapper
import FirebaseDatabase
extension Mapper {
public func map(snapshot: FIRDataSnapshot) -> N? {
guard var json = snapshot.value as? [String : AnyObject] else { return nil }
json["id"] = snapshot.key as AnyObject
if let mappingObject = Mapper<N>().map(JSON: json) {
return mappingObject
}
return nil
}
}
Mapper
を拡張し、FIRDataSnapshot
を引数で受け取って、生成するようにすると、key
をid
に代入したマッピングを行うことが出来ます!
FIRDatabase.database().reference().child("articles").child(articleId).observeSingleEvent(of: .value, with: { (snapshot) in
if let json = snapshot.value as? [String : AnyObject] {
let article = Mapper<Article>().map(JSON: json)
print("\(article)") // idとtitleが格納されている!
}
}
感想
僕の中では普段から使っているObjectMapper
を利用することに落ち着いたのですが、
ぜひFirebaseをガンガン使ってる方のノウハウを知りたいので、教えてもらえると嬉しいです!