はじめに
ニフクラを利用した iOS アプリを開発していた際に、ニフクラのデータストアのレコードに対する読み出し・書き込みの処理に現在時刻を使用する必要があり、実装方法を検討しました。
端末側で取得する「現在時刻」は当てにならない
iOS デバイス側では時刻を任意に設定できてしまうため、iOS アプリ側で次のようにして時刻を取得すると、実際の現在時刻とは異なる時刻を現在時刻として扱ってしまう可能性があります。
// 端末の時間を任意に設定できるため
// 本当の現在時刻が取得できるとは限らない
let date = Date()
ニフクラ側で現在時刻を取得する
ニフクラ側から現在時刻を返してもらえるような機能1が用意されているか少し調べてみましたが見つかりませんでした2。そこで今回は、ニフクラのスクリプト機能により iOS アプリからニフクラに現在時刻を問い合わせるという方法をとることにしました。
現在時刻を返すスクリプト
ニフクラから現在時刻を返すためのスクリプトの例を以下に示します。
module.exports = function (req, res) {
res.status(200).json(new Date());
}
このスクリプトをニフクラのコンソールからアップロードします。アップロード時に選択するメソッドは GET
にしておくものとして、以下でこのスクリプトをアプリ側から実行する方法について説明します。
iOS アプリからスクリプトを実行する
上に示したスクリプト getCurrentTime.js
を iOS アプリから実行する方法を説明します。iOSアプリの開発環境は以下のとおりです。
- Xcode v11.1 (11A1027)
- ニフクラ mobile backend iOS SDK v3.0.23
ニフクラが提供する SDK を使ってスクリプトを実行し、スクリプトが返す値をデコードすればよいのですが、デコードする際には注意が必要です。
JSONDecoder
はデフォルトでは yyyy-MM-dd'T'HH:mm:ssZ
形式の日時を扱うことを前提としているらしく、ニフクラが返す yyyy-MM-dd'T'HH:mm:ss.SSSZ
形式(ミリ秒が含まれている)の日時をデコードすることができません。
以下のようにして、想定している日付フォーマットを JSONDecoder
クラスの dateDecodingStrategy
に指定してからデコードすると、期待どおりの結果が得られるようになります。
let script = NCMBScript(name: "getCurrentTime.js", method: .executeWithGetMethod)!
script.execute(nil, headers: nil, queries: nil) { data, error in
if let error = error {
// TODO: エラー処理
return
}
guard let data = data else {
// TODO: エラー処理
return
}
// デフォルトのJSONDecoderでは
// ニフクラが返す日時情報をデコードできないため、
// dateDecodingStrategyの設定が必要
let decoder = JSONDecoder()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
decoder.dateDecodingStrategy = .formatted(formatter)
do {
let date = try decoder.decode(Date.self, from: data)
// TODO: 得られた現在時刻を利用する
} catch {
// TODO: エラー処理
}
}
-
Cloud Firestore で提供されている
serverTimestamp()
のようなAPIがあるのが理想的でした。 ↩ -
古い情報ですが、ニフクラのユーザコミュニティでもサーバ側の現在時刻を取得する方法について言及がありました。そこでは、サーバ時間の取得方法として、データストアで適当なデータを作成して
createDate
やupdateDate
の値を参照する方法が提案されていました。
https://github.com/NIFCloud-mbaas/UserCommunity/issues/260 ↩ -
ニフクラ mobile backend Swift SDK も提供されていますが、そちらは Deployment Target が iOS 12.0 のため、今回はより古い OS バージョンを対象とするアプリでも利用可能は ニフクラ mobile backend iOS SDK の方を使用しています。(将来的には Swift SDK の方も使っていきたいと思っています。) ↩