※ 執筆時点(2021年09月現在)で検証中です
2021年09月現在、NCMBのSwift SDKをSwiftUIで利用している場合、初期化処理は次のように行うのが基本となっています。
import SwiftUI
import NCMB
@main
struct NCMBTestApp: App {
@Environment(\.scenePhase) var scenePhase
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { scene in
switch scene {
case .active:
print("Initialize NCMB")
// APIキーの設定とSDK初期化
NCMB.initialize(applicationKey: "YOUR_APPLICATION_KEY", clientKey: "YOUR_CLIENT_KEY")
case .background: break
case .inactive: break
@unknown default: break
}
}
}
}
画面が前面、バックグラウンド、アクティブではなくなったタイミングを使って判定しています。Xcode 12までは特に問題なかったのですが、Xcode 13/Swift 5.5にしたところ、emptyApplicationKeyというエラーが出るようになりました。
原因
ContentViewなど、呼び出される画面においてonAppearを使って、そこでデータの取得を行っていました。
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, world!")
.padding()
}.onAppear() {
query()
}
}
func query() {
print("Execute NCMBQuery")
let query = NCMBQuery.getQuery(className: "Test")
let results = query.find()
if case let .failure(err) = results {
print(err) // emptyApplicationKey
}
}
}
これは、初期化処理が行われる前にNCMBのAPIを利用した場合に起こるエラーです。
実際、デバッグメッセージを入れて、処理順番を見ると、NCMBQueryの処理が初期化前に実行されてしまいます。
Execute NCMBQuery
emptyApplicationKey // ← エラーメッセージ
Initialize NCMB
解決策
解決策としては、初期化処理もonAppearで行うことでしょう。
//
// NCMBTestApp.swift
// NCMBTest
//
// Created by Atsushi on 2021/09/22.
//
import SwiftUI
import NCMB
@main
struct NCMBTestApp: App {
@Environment(\.scenePhase) var scenePhase
var body: some Scene {
WindowGroup {
VStack {
ContentView()
}
.onAppear() {
print("Initialize NCMB")
// APIキーの設定とSDK初期化
NCMB.initialize(applicationKey: "YOUR_APPLICATION_KEY", clientKey: "YOUR_CLIENT_KEY")
}
}
}
}
ContentViewのonAppearだと、やはり初期化の方が遅くなってしまうので、ダミーでVStackを定義して、それのonAppearを利用するのが良いようです。こうすることで、初期化処理とNCMBQueryの実行が、予定していた通りに行われるようになります。
まとめ
Xcode13/Swift 5.5になって、イベントの発火タイミングが変わったのかも知れません。利用されている方はご注意ください。