ニフクラ 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()
}
}
}
構造体の定義
今回は以下のような構造体(ユーザー、ロール)を定義します。
struct User: ParseUser {
// ParseObjectの必須プロパティ
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var originalData: Data?
// ParseUserの必須プロパティ
var username: String?
var email: String?
var emailVerified: Bool?
var password: String?
var authData: [String: [String: String]?]?
// 独自のプロパティ
var customKey: String?
var scores: ParseRelation<Self>?
}
struct Role<RoleUser: ParseUser>: ParseRole {
// ParseObjectの必須プロパティ
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var originalData: Data?
// ParseRoleの必須プロパティ
var name: String?
}
struct GameScore: ParseObject {
// ParseObjectの必須プロパティ
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var originalData: Data?
// 独自のプロパティ
var points: Int?
}
ロールの作成
ロールは子ロールと、ユーザーを持つことができます。以下の例では、 Administrator
というロールを作成しています。
// 後述のために保存したロールを保持する変数
var savedRole: Role<User>?
// ACLの定義。現在のユーザーだけが読み書き可能
guard let currentUser = User.current else {
fatalError("User currently is not signed in")
}
var acl = ParseACL()
acl.setReadAccess(user: currentUser, value: true)
acl.setWriteAccess(user: currentUser, value: true)
// ロールの作成と保存
let adminRole = try Role<User>(name: "Administrator", acl: acl)
adminRole.save { result in
switch result {
case .success(let saved): // 保存成功
// 後で使うように保存したロールを保持
savedRole = saved
case .failure(let error): // 保存失敗
print("Error saving role: \(error)")
}
}
ロールにユーザーを追加する
既存のロールに対して、新しいユーザーを追加する場合のコードです。
try savedRole!.users?.add([User.current!]).save { result in
switch result {
case .success(let saved): // 保存成功
case .failure(let error): // 保存失敗
print("Error saving role: \(error)")
}
}
所属するユーザーを取得する
ロールに所属するユーザーを取得する場合は、 ParseQuery
を使います。
let query: Query<User>? = try savedRole!.users?.query()
query?.find { result in
switch result {
case .success(let relatedUsers): // 取得成功
case .failure(let error): // 取得失敗
print("Error querying role: \(error)")
}
}
ロールからユーザーを削除する
ロールからユーザーを消す場合には remove
を使います。もちろんACLの設定によっては、削除できない場合もあります。
try savedRole!.users?.remove([User.current!]).save { result in
switch result {
case .success(let saved):
print("The role removed successfully: \(saved)")
print("Check \"users\" field in your \"Role\" class in Parse Dashboard.")
case .failure(let error):
print("Error saving role: \(error)")
}
}
既存のロールに新しいロールを追加する
ロールは入れ子の構造にできます。以下の例では、 Administrator
ロールに moderatorRole
ロールを追加しています。
try savedRole!.roles?.add([moderatorRole!]).save { result in
switch result {
case .success(let saved): // 保存成功
case .failure(let error): // 保存失敗
print("Error saving role: \(error)")
}
}
子ロールを取得する
子ロールを取得する際には queryRoles
を使います。
try savedRole!.queryRoles().find { result in
switch result {
case .success(let relatedRoles): // 取得成功
case .failure(let error): // 取得失敗
print("Error querying role: \(error)")
}
}
子ロールを削除する
子ロールを削除する場合には remove
を使います。
try savedRole!.roles?.remove([savedRoleModerator!]).save { result in
switch result {
case .success(let saved):
print("The role removed successfully: \(saved)")
print("Check the \"roles\" field in your \"Role\" class in Parse Dashboard.")
case .failure(let error):
print("Error saving role: \(error)")
}
}
まとめ
Parse Serverのロールオブジェクトは、NCMBと変わらず利用できます。ユーザーを入れる形もそうですし、ロールを入れ子にできるのもNCMBと変わりません。
ACLの仕組みもParse ServerとNCMBで似ています。他のmBaaSと比べると、全体の修正量はそこまで多くないと思われます。載せ替え先として検討に挙げてください。