Parse Server Swift SDKの使い方（デバイストークンとプッシュ通知）

[ニフクラ mobile backendは3月末で終了します](https://mbaas.nifcloud.com/info/2023/12/post-171.html)。

ニフクラ mobile backendからの移行先として、お勧めしているのが[Parse Server](https://parseplatform.org/)です。設計思想が近く、変更するコード量が少なく済むのではないかと思います。

Parse ServerではiOS向けにSDKを提供していますが、Swift SDKについてはあまりドキュメントが充実していません。そこで、各機能の使い方を解説します。今回はプッシュ通知の送信に利用する、ParseInstallationの使い方を紹介します。

## Swift SDKとObjective-C SDKのどちらを使うべきか

Parse ServerにはSwift SDKと[Objective-C SDK](https://docs.parseplatform.org/ios/guide/)が用意されています。機能的にいうと、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をインポートします。

```swift
import ParseSwift
```

## 初期化

SwiftUIの例です。初期化は `(アプリ名)App.swift` にて行います。そして、初期化は `ParseSwift.initialize` にて行います。指定するアプリケーションID、クライアントキー、サーバーURLはそれぞれParse Serverを立ち上げる際に指定したものを使います。

マスターキーも指定できるようですが、アプリ側では使わない方が良いかと思います。

```swift
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()
        }
    }
}
```

## ParseInstallationの使い方

まず、ParseInstallationを継承した構造体を用意します。

```swift
struct Installation: ParseInstallation {
    //: 以下はParseObjectの必須フィールドです
    var objectId: String?
    var createdAt: Date?
    var updatedAt: Date?
    var ACL: ParseACL?

    //: 以下はParseInstallationの必須フィールドです
    var installationId: String?
    var deviceType: String?
    var deviceToken: String?
    var badge: Int?
    var timeZone: String?
    var channels: [String]?
    var appName: String?
    var appIdentifier: String?
    var appVersion: String?
    var parseVersion: String?
    var localeIdentifier: String?

    //: 追加でカスタムフィールドを定義できます
    var customKey: String?
}
```

## デバイストークンの取得

デバイストークンは以下のコードで取得・保存できます。

```swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
	guard var currentInstallation = Installation.current else {
			return
	}
	currentInstallation.setDeviceToken(deviceToken)
	currentInstallation.channels = ["global"] // その他の条件付けがあれば
	currentInstallation.save { _ in }
}
```


## デバイストークンの更新

デバイストークンは `Installation.current` で取得できます。後は項目を任意に変更して、Parse Serverへ保存できます。

```swift
Installation.current?.save { results in
    switch results {
    case .success(let updatedInstallation):
        print("更新しました")
    case .failure(let error):
        print("更新エラー： \(error)")
    }
}
```

基本的に利用できる項目は以下の通りです。

| 項目             | 読み取り専用 | 説明                                                                                                                                                                                                                                                                                                  |
| ---------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| installationId   | ○            | Parseが使用するデバイスの一意のID                                                                                                                                                                                                                                                                     |
| deviceType       | ○            | デバイスのタイプ。"ios"、"osx"、"android"、"winrt"、"winphone"、"dotnet"、"embedded"のいずれか。iOSデバイスでは、このフィールドは"ios"に設定されます                                                                                                                                          |
| pushType         | ○            | Parseが使用するプッシュ配信ネットワークを指定するためのフィールド。デバイスがFCM経由でプッシュを受信するように登録されている場合、このフィールドは"gcm"とマークされます。Google Playサービスが利用できない場合、このフィールドは空白になります                                                        |
| deviceToken      | ○            | FCMが登録IDを追跡するために使用するトークン。                                                                                                                                                                                                                                                         |
| appName          | ○            | このインストールが属するクライアントアプリケーションの表示名。この値は、デバイスからParseInstallationオブジェクトが保存されるたびに同期されます                                                                                                                                                       |
| appVersion       | ○            | このインストールが属するクライアントアプリケーションのバージョン文字列。この値は、デバイスからParseInstallationオブジェクトが保存されるたびに同期されます                                                                                                                                             |
| parseVersion     | ○            | このインストールが使用するParse SDKのバージョン。この値は、デバイスからParseInstallationオブジェクトが保存されるたびに同期されます                                                                                                                                                                    |
| timeZone         | ○            | ターゲットデバイスが現在位置しているタイムゾーン。この値は、デバイスからParseInstallationオブジェクトが保存されるたびに同期されます                                                                                                                                                                   |
| localeIdentifier | ○            | デバイスのロケール識別子。形式は[言語コード]-[国コード]。言語コードはISO 639-1で定義されている2文字の小文字のISO言語コード（例："en"）。国コードはISO 3166-1で定義されている2文字の大文字のISO国コード（例："US"）。この値は、デバイスからParseInstallationオブジェクトが保存されるたびに同期されます |
| badge            |              | iOSアプリのアイコンバッジの現在の値。サーバー上でこの値が変更されると、将来のバッジ増分プッシュ通知に使用されます                                                                                                                                                                                     |
| channelUris      | ○            | WindowsデバイスのためのMicrosoftが生成したプッシュURI                                                                                                                                                                                                                                                 |
| appIdentifier    | ○            | このインストールのクライアントアプリケーションの一意の識別子。このパラメータはAndroidではサポートされていません                                                                                                                                                                                       |

## デバイストークンのデータ取得

デバイストークンのデータ取得は以下のようにして行います。

```swift
Installation.current?.fetch { results in
    switch results {
    case .success(let fetchedInstallation):
        print("取得成功しました: \(fetchedInstallation)")
    case .failure(let error):
        print("取得失敗しました: \(error)")
    }
}
```

## アプリからのプッシュ通知作成

アプリからのプッシュ通知を作成する際のコードです。Parse Serverの設定で、アプリからのプッシュ通知を許可している必要があります。

```swift
// プッシュ通知のメッセージ
let helloAlert = ParsePushAppleAlert(body: "Hello from ParseSwift!")
let applePayload = ParsePushPayloadApple(alert: helloAlert)
    .setBadge(1)

// プッシュ作成
let installationQuery = Installation.query(isNotNull(key: "objectId"))
let push = ParsePush(payload: applePayload, query: installationQuery)

// プッシュ通知送信
push.send { result in
    switch result {
    case .success(let statusId):
        print("プッシュ通知送信: \"\(statusId)\"")
    case .failure(let error):
        print("エラー: \(error)")
    }
}
```

## プッシュ通知の検索

プッシュ通知を検索する際には、クエリーを利用します。以下の例では、objectIdがある全てのプッシュ通知を取得しています。

```swift
let query = ParsePushStatus<ParsePushPayloadAny>
    .query(isNotNull(key: "objectId"))
query.findAll(options: [.useMasterKey]) { result in
    switch result {
    case .success(let pushStatus):
        print("プッシュ通知検索結果: \"\(pushStatus)\"")
    case .failure(let error):
        print("クエリーエラー: \(error)")
    }
}
```

## まとめ

Parse ServerとNCMBでは、基本的な思想が似ています。デバイストークンの登録や、プッシュ通知の作成においても、NCMBと同じような使い方ができます。また、プッシュ通知は管理画面でビジュアル的に作成できるので、それも便利です。

他のmBaaSと比べると、移行時における全体の修正量はそこまで多くないと思われます。載せ替え先として検討に挙げてください。

[parse\-community/Parse\-Swift: The Swift SDK for Parse Platform \(iOS, macOS, watchOS, tvOS, Linux, Android, Windows\)](https://github.com/parse-community/Parse-Swift)