SwiftUI を使用してバックグラウンドでデータを同期する - Swift SDK
項目一覧
Overview
SwiftUI BackupTask{ を使用できます アプリがバックグラウンドで稼働しているときに 同期された邦土を更新するにはこの例では、 iOSアプリでバックグラウンド同期を構成および実行する方法を説明します。
SwiftUI Device Sync テンプレート アプリを使用して、このページの例に従うことができます。 テンプレート アプリの独自のコピーを取得するには、DeviceDevice SyncSwiftUI SyncSwiftUIDevice SyncGo 確認し、 4} セクションとPrerequisites Start with the Templateセクションを確認してください。
アプリのバックグラウンド モードを有効にする
アプリのバックグラウンド タスクを有効にするには、次の手順に従います。
バックグラウンド タスクのスケジュール
アプリのバックグラウンド プロセスを有効にした後、アプリへのコードの追加を開始して、バックグラウンド タスクをスケジュールおよび実行できます。 まず、このコードを記述するファイルにBackgroundTasks
をインポートします。
import SwiftUI import RealmSwift import BackgroundTasks
スケジュールされたバックグラウンド タスクを追加できるようになりました。 テンプレート アプリを使用してアプリを実行している場合は、 @main
ビューをアップデートできます。
@main struct realmSwiftUIApp: SwiftUI.App { private var phase (\.scenePhase) var body: some Scene { WindowGroup { ContentView(app: realmApp) } .onChange(of: phase) { newPhase in switch newPhase { case .background: scheduleAppRefresh() default: break } } }
scenePhase
: @Environment(\.scenePhase) private var phase
への変更を保存するための環境変数を追加できます。
次に、アプリがバックグラウンドになるときにscheduleAppRefresh()
関数を呼び出す.onChange(of: phase)
ブロックを追加できます。
scheduleAppRefresh()
関数を作成します。
func scheduleAppRefresh() { let backgroundTask = BGAppRefreshTaskRequest(identifier: "refreshTodoRealm") backgroundTask.earliestBeginDate = .now.addingTimeInterval(10) try? BGTaskScheduler.shared.submit(backgroundTask) }
これにより、バックグラウンド モードを有効にしたときに 上記で Index.plist に追加した識別子を持つバックグラウンド タスクが実行されるようスケジュールされます。 この例では、識別子refreshTodoRealm
がこのタスクを参照しています。
バックグラウンド タスクの作成
バックグラウンド タスクをスケジュールしたので、同期された Realm を更新するために実行されるバックグラウンド タスクを作成する必要があります。
テンプレート アプリで次のアプリを使用している場合は、 .onChange(of: phase)
の後にこのbackgroundTask
を@main
ビューに追加できます。
.onChange(of: phase) { newPhase in switch newPhase { case .background: scheduleAppRefresh() default: break } } .backgroundTask(.appRefresh("refreshTodoRealm")) { guard let user = realmApp.currentUser else { return } let config = user.flexibleSyncConfiguration(initialSubscriptions: { subs in if let foundSubscription = subs.first(named: "user_tasks") { foundSubscription.updateQuery(toType: Item.self, where: { $0.owner_id == user.id }) } else { subs.append(QuerySubscription<Item>(name: "user_tasks") { $0.owner_id == user.id }) } }, rerunOnOpen: true) await refreshSyncedRealm(config: config) }
このバックグラウンド タスクは、まずアプリにログインしているユーザーがあることを確認します。 その場合、 .FlexibleSyncConfigurationが設定されます アプリがRealmを同期するために使用できるサブスクライブ。
これは、テンプレート アプリのContentView
で使用されるのと同じ構成です。 ただし、ここで使用するには、ビュー階層のはるかに上にある へのアクセスが必要です。 これを、ユーザーをパラメーターとして受け取り、 Realm.config を返すいずれのビューからでも呼び出せる関数にリファクタリングできます。
最後に、このタスクは Realm を実際に同期する関数の結果を待ちます。 この関数を追加します。
func refreshSyncedRealm(config: Realm.Configuration) async { do { try await Realm(configuration: config, downloadBeforeOpen: .always) } catch { print("Error opening the Synced realm: \(error.localizedDescription)") } }
この同期された Realm を開き、 downloadBeforeOpen
パラメーターを使用してアップデートをダウンロードすることを指定すると、新しいデータが Realm にバックグラウンドでロードされます。 その後アプリが再度開くと、デバイス上の更新されたデータがすでに存在しています。
重要
このバックグラウンド タスクで、Realm に直接書き込まないでください。 Realm のスレッドセーフなアーキテクチャにより、スレッド関連の問題が発生する可能性があります。
タスクのバックグラウンドをテストする
バックグラウンド タスクをスケジュールするときは、システムがタスクを実行できる最速の時間を設定します。 ただし、オペレーティング システムは他の多くの考慮事項を考慮し、予定されたearliestBeginDate
の後にバックグラウンド タスクの実行が遅れる可能性があります。 デバイスがバックグラウンド タスクを実行するのを待ってから、意図した結果を実行することを確認する代わりに、ブレークポイントを設定し、LDDB を使用してタスクを呼び出すことができます。
アプリを実行するためのデバイスの構成
バックグラウンド タスクがバックグラウンドで同期された Realm を更新していることをテストするには、少なくとも iOS 16を実行している物理デバイスが必要です。 デバイスは 開発者モード で実行するように構成されている必要があります 。Untrusted Developer
通知を受け取った場合は、Settings、General、VPN & Device Management にGoします。 ここで、開発しているアプリを実行することを確認できます。
デバイス上でアプリを正常に実行できたら、バックグラウンドのタスクをテストできます。
ブレークポイントを設定する
まず、 scheduleAppRefresh()
関数にブレークポイントを設定します。 BGTaskScheduler
にタスクを送信する行の後にブレークポイントを設定します。 この例では、 print
行を追加し、出力行にブレークポイントを設定できます。
func scheduleAppRefresh() { let backgroundTask = BGAppRefreshTaskRequest(identifier: "refreshTodoRealm") backgroundTask.earliestBeginDate = .now.addingTimeInterval(10) try? BGTaskScheduler.shared.submit(backgroundTask) print("Successfully scheduled a background task") // Set a breakpoint here }
Atlas でのデータの追加または変更
アプリがバックグラウンドではありますが、Xcode で実行中のままである間に、デバイスに同期する必要がある新しいドキュメントを関連する Atlas コレクションに挿入します。 あるいは、デバイスから作成した既存のドキュメントの 値を変更します。 バックグラウンド タスクを正常に実行すると、このデータがバックグラウンド プロセスからデバイスに同期されたことが表示されます。
SwiftUI テンプレート アプリを使用している場合は、Atlas クラスターのItem
コレクションから関連するドキュメントを見つけることができます。 Atlas でドキュメントを追加または変更する方法の詳細については、「 MongoDB Atlas: ドキュメントの作成、表示、更新、削除 」を参照してください。
LDDB でのバックグラウンド タスクの呼び出し
LDDB でバックグラウンド タスクを手動で実行するには、次のコマンドを使用します。
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"refreshTodoRealm"]
バックグラウンド タスクに別の識別子を使用した場合は、 refreshTodoRealm
をタスクの識別子に置き換えます。 これにより、タスクはすぐに実行を開始できます。
成功した場合は、次のようなものが表示されます。
2022-11-11 15:09:10.403242-0500 App[1268:196548] Simulating launch for task with identifier refreshTodoRealm 2022-11-11 15:09:16.530201-0500 App[1268:196811] Starting simulated task
タスクを開始した後、Xcode デバッグ パネルの [ Continue program execution ] ボタンを使用してアプリの実行を再開します。