NCMBのNCMBSubclassing
について触れられている情報が少ないと感じましたので、簡単な内容ですが投稿します。無駄な説明は省いて、重要なポイントだけシンプルに示します。
動作確認環境
- NCMB 2.2.5
- OS X EI Capitan 10.11.2 (15C50)
- Xcode Version 7.2.1 (7C1002)
- iPhone 6s Plus (iOS 9.2.1)
対象のデータストア
NCMBObjectをサブクラス化しない場合
func addLocation() {
// ...サブクラス化した場合と同じなので省略
let location = NCMBObject(className: "Location")
location.setObject(geoPoint, forKey: "geoPoint")
location.setObject("新宿駅", forKey: "name")
// ...サブクラス化した場合と同じなので省略
}
NCMBObjectをサブクラス化した場合
/// 位置情報をデータストアに追加します
func addLocation() {
let latitude = Double(35.690921)
let longitude = Double(139.700258)
let geoPoint = NCMBGeoPoint(latitude: latitude, longitude: longitude)
let location = Location.object() as! Location
location.geoPoint = geoPoint
location.name = "新宿駅"
location.saveInBackgroundWithBlock { error in
if let e = error {
print("保存失敗: \(e)")
return
}
print("保存成功")
}
}
/// ストアデータの位置情報を検索します
func searchLocation() {
let latitude = Double(35.690921)
let longitude = Double(139.700258)
let geoPoint = NCMBGeoPoint(latitude: latitude, longitude: longitude)
let geoQuery = Location.query()
// 現在のSDKでは、検索対象フィールド(プロパティ)を文字列で指定しなければいけないのが残念
geoQuery.whereKey("geoPoint", nearGeoPoint: geoPoint, withinKilometers: Double(2.0))
geoQuery.limit = 20
do {
let points = try geoQuery.findObjects() as NSArray
for point in points as! [Location] {
print(point.name)
}
} catch {
print("失敗: \(error)")
}
}
このようにNCMBObjectをサブクラス化した場合は、
- 若干ソースコードの可読性が向上する
- プロパティの型チェックが行われる
という最低でも2つのメリットが得られると思います。
サブクラス化したLocationクラスの内容
一目瞭然ですが、NCMBのSDKはSwiftで記述されていないので、プロパティ名とオブジェクトの出し入れをする際のキー名が一致していることが重要です。 また、NCMBSubclassingプロトコルに準拠する必要があります。 @objc
属性が必要であることにも注意してください。
import NCMB
@objc(Location) // この宣言をしないと、サブクラスの登録時にクラッシュします
public class Location: NCMBObject, NCMBSubclassing {
var name: String! {
get {
return objectForKey("name") as! String
}
set {
setObject(newValue, forKey: "name")
}
}
var geoPoint: NCMBGeoPoint {
get {
return objectForKey("geoPoint") as! NCMBGeoPoint
}
set {
setObject(newValue, forKey: "geoPoint")
}
}
// MARK: - NCMBSubclassing Protocol
/// mobile backend上のクラス名を返す
/// - returns: サブクラスのデータストア上でのクラス名
public static func ncmbClassName() -> String! {
return "Location" // クラス名と同じ名前であること
}
}
サブクラス化したクラスを使用するための前準備
func setupNCMB() {
// NCMBSubclassingに準拠しているクラスのセットアップ
Location.registerSubclass()
// NCMBのセットアップ
NCMB.setApplicationKey(applicationKey, clientKey: clientKey)
}
このように、NCMBのセットアップの直前で、サブクラスを登録する必要があります。
まとめ
NCMBに限らず、Parseやその他のmBaaSのSDKでも同様に、基底クラスをサブクラス化する仕組みが提供されているので、できるだけ利用した方が良いと思います。今後SDKがSwift対応すれば、クラスの記述もよりSwiftらしい記述ができるようになるはずです。(ParseSDKはすでにそうなっています)
余計なコードが入っていますが、本記事で説明したコードもありますので、参照されたい方はどうぞ。
https://github.com/naokits/my-programming-marathon/tree/master/NCMB_iOSAppDemo