12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NCMBObjectはサブクラス化して使おう!

Posted at

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)

対象のデータストア

ncmb-data-store.png

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

関連情報

12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?