ニフクラ mobile backendは3月末で終了します。
ニフクラ mobile backendからの移行先として、お勧めしているのがParse Serverです。設計思想が近く、変更するコード量が少なく済むのではないかと思います。
Parse ServerではiOS向けにSDKを提供していますが、Swift SDKについてはあまりドキュメントが充実していません。そこで、各機能の使い方を解説します。今回は位置情報オブジェクトの使い方を紹介します。
Swift SDKとObjective-C SDKのどちらを使うべきか
Parse ServerにはSwift SDKとObjective-C SDKが用意されています。機能的にいうと、Objective-C SDKの方が多いようです。しかし、公式メッセージとしてはSwift SDKを使っていくのを奨励しています。
Parse Server Swift SDKのインストール
Swift SDKのインストールは、CocoaPodsやCarthageなどが使えます。しかし、一番簡単なのはXcodeのPackage Dependenciesを使う方法でしょう。
XcodeのFileメニューより、Add Package Dependenciesを選択して、出てきたダイアログで以下のURLを指定します。
https://github.com/parse-community/Parse-Swift.git
そして、利用するファイルでSDKをインポートします。
import ParseSwift
初期化
SwiftUIの例です。初期化は (アプリ名)App.swift
にて行います。そして、初期化は ParseSwift.initialize
にて行います。指定するアプリケーションID、クライアントキー、サーバーURLはそれぞれParse Serverを立ち上げる際に指定したものを使います。
マスターキーも指定できるようですが、アプリ側では使わない方が良いかと思います。
import SwiftUI
import ParseSwift
@main
struct ParseDemoApp: App {
init() {
ParseSwift.initialize(applicationId: "YOUR_APP_ID", clientKey: "YOUR_CLIENT_KEY", serverURL: URL(string: "https://example.com/parse")!)
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
構造体の定義
位置情報オブジェクトは、データストアの1フィールドとして用います。ParseGeoPointが位置情報オブジェクトを保存するフィールド定義になります。
struct GameScore: ParseObject {
//: ParseObjectの必須プロパティ
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var location: ParseGeoPoint?
var originalData: Data?
//: 独自のプロパティ
var points: Int?
}
位置情報オブジェクトのセット
ParseGeoPoint
を該当フィールドに対して適用します。1つ目の引数が緯度、2つ目の引数が経度です。
var score = GameScore(points: 10)
do {
try score.location = ParseGeoPoint(latitude: 40.0, longitude: -30.0)
}
位置情報オブジェクトの保存
保存は通常のデータストアと同じく save
メソッドを使います。
score.save { result in
switch result {
case .success(let savedScore):
assert(savedScore.objectId != nil)
assert(savedScore.createdAt != nil)
assert(savedScore.updatedAt != nil)
assert(savedScore.points == 10)
assert(savedScore.location != nil)
guard let location = savedScore.location else {
print("エラー")
return
}
print(location)
case .failure(let error):
assertionFailure("保存エラー: \(error)")
}
}
位置情報を使った検索
以下は位置情報を使った検索例です。 near
は指定した位置から近い順に検索します。
let pointToFind = try ParseGeoPoint(latitude: 40.0, longitude: -30.0)
constraints.append(near(key: "location", geoPoint: pointToFind))
query = GameScore.query(constraints)
query.find { results in
switch results {
case .success(let scores):
assert(scores.count >= 1)
scores.forEach { (score) in
// 何か処理
}
case .failure(let error):
assertionFailure("クエリーエラー: \(error)")
}
}
並び替えを別途指定することもできます。
var querySorted = query
querySorted.order([.descending("points")])
querySorted.find { results in
switch results {
case .success(let scores):
assert(scores.count >= 1)
scores.forEach { (score) in
// 何か処理
}
case .failure(let error):
assertionFailure("クエリーエラー: \(error)")
}
}
他の条件を含める
位置情報以外の条件を含めることもできます。
constraints.append("points" > 9)
var query2 = GameScore.query(constraints)
query2.find { results in
switch results {
case .success(let scores):
assert(scores.count >= 1)
scores.forEach { (score) in
// 何か処理
}
case .failure(let error):
assertionFailure("クエリーエラー: \(error)")
}
}
位置情報がないものを検索
位置情報が設定されていないものを検索する場合には、 doesNotExist
を使います。
var query3 = GameScore.query("points" > 50, doesNotExist(key: "location"))
query3.find { results in
switch results {
case .success(let scores):
scores.forEach { (score) in
// 何か処理
}
case .failure(let error):
assertionFailure("Error querying: \(error)")
}
}
位置情報が空のものを検索
フィールドはあっても、値が設定されていないものを検索する場合には、 isNull
を使います。
var anotherQuery3 = GameScore.query("points" > 50, isNull(key: "location"))
anotherQuery3.find { results in
switch results {
case .success(let scores):
scores.forEach { (score) in
// 何か処理
}
case .failure(let error):
assertionFailure("クエリーエラーError querying: \(error)")
}
}
ポリゴン検索
Parse ServerではNCMBにはない、3カ所以上の位置情報を用いたポリゴン検索ができます。
let points: [ParseGeoPoint] = [
try .init(latitude: 35.0, longitude: -28.0),
try .init(latitude: 45.0, longitude: -28.0),
try .init(latitude: 39.0, longitude: -35.0)
]
let query9 = GameScore.query(withinPolygon(key: "location", points: points))
query9.find { results in
switch results {
case .success(let scores):
scores.forEach { (score) in
// 何か処理
}
case .failure(let error):
assertionFailure("Error querying: \(error)")
}
}
まとめ
Parse Serverの位置情報オブジェクトは、NCMBと変わらず利用できます。また、Parseにはポリゴンという複数の位置情報を利用したオブジェクトも利用できます。地図を利用したアプリなどで活躍することでしょう。
データの管理方法などはParse ServerとNCMBで似ています。他のmBaaSと比べると、全体の修正量はそこまで多くないと思われます。載せ替え先として検討に挙げてください。