문서 메뉴
문서 홈
/ /
Atlas Device SDK
/ /

SwiftUI를 사용하여 백그라운드에서 데이터 동기화 - Swift SDK

이 페이지의 내용

  • 개요
  • 앱의 백그라운드 모드 활성화
  • 백그라운드 모드 기능 추가
  • 백그라운드 모드 선택
  • Info.plist 업데이트
  • 백그라운드 작업 예약
  • 백그라운드 작업 생성
  • 백그라운드 작업 테스트
  • 앱 실행을 위한 장치 구성
  • 중단점 설정
  • 앱 실행하기
  • Atlas에서 데이터 추가 또는 변경
  • LLDB에서 백그라운드 작업 호출
  • 장치에서 비행기 모드 켜기
  • 앱 열기

SwiftUI BackgroundTask 를 사용할 수 있습니다. 앱이 백그라운드에 있을 때 동기화된 Realm을 업데이트합니다. 이 예제는 iOS 앱에서 백그라운드 동기화를 구성하고 수행하는 방법을 보여줍니다.

SwiftUI Device Sync Template 앱을 사용하여 이 페이지의 예제를 따라할 수 있습니다. SwiftUI Device Sync Template 앱의 사본을 얻으려면 Device Sync SwiftUI 튜토리얼PrerequisitesStart with the Template 섹션으로 Go 합니다.

앱에 백그라운드 작업을 활성화하는 방법:

1

앱 Target을 선택하고 Signing & Capabilities 탭으로 이동한 다음 + Capability을 클릭하여 기능을 추가합니다.

앱 Target이 선택되고 서명 & 기능 탭이 열려 있고 기능 추가를 가리키는 화살표가 표시된 Xcode의 스크린샷입니다.
클릭하여 확대

'백그라운드'로 검색해 Background Modes 선택합니다.

2

이제 Signing & Capabilities 탭에 Background Modes 섹션이 표시됩니다. 이 섹션을 확장하고 확인 상자를 클릭해 Background fetchBackground processing를 활성화합니다.

3

프로젝트의 Info.plist로 이동하여 Permitted background task scheduler identifiers에 대한 새 행을 추가합니다. 원시 키와 값을 볼 경우 키는 BGTaskSchedulerPermittedIdentifiers입니다. 이 필드는 배열입니다. 백그라운드 작업 식별자를 위해 새 항목을 추가합니다. 새 항목의 값을 백그라운드 작업의 식별자로 사용할 문자열로 설정합니다. 예: refreshTodoRealm.

앱의 백그라운드 프로세스를 활성화한 후 앱에 코드를 추가하여 백그라운드 작업을 예약하고 실행할 수 있습니다. 먼저 이 코드를 쓸 파일에서 BackgroundTasks을 가져옵니다.

import SwiftUI
import RealmSwift
import BackgroundTasks

이제 예정된 백그라운드 작업을 추가할 수 있습니다. Template 앱을 통해 팔로우하는 경우 @main 보기를 업데이트할 수 있습니다.

@main
struct realmSwiftUIApp: SwiftUI.App {
@Environment(\.scenePhase) private var phase
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()scheduleAppRefresh() 함수를 생성합니다.

func scheduleAppRefresh() {
let backgroundTask = BGAppRefreshTaskRequest(identifier: "refreshTodoRealm")
backgroundTask.earliestBeginDate = .now.addingTimeInterval(10)
try? BGTaskScheduler.shared.submit(backgroundTask)
}

이렇게 하면 백그라운드 모드를 활성화할 때 위의 Info.plist에 식별자를 추가한 백그라운드 작업을 실행하도록 작업이 예약됩니다. 이 예제에서 식별자 refreshTodoRealm은 이 작업을 합니다.

이제 백그라운드 작업을 예약했으니 동기화된 Realm을 업데이트하기 위해 실행할 백그라운드 작업을 생성해야 합니다.

Template 앱을 팔로우하는 경우 .onChange(of: phase) 다음 @main 보기에 이 backgroundTask을 추가할 수 있습니다.

.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을 동기화하는 데 사용할 수 있는 구독 으로 설정합니다.

이는 Template 앱의 ContentView 에 사용된 것과 동일한 구성입니다. 그러나 여기에서 사용하려면 뷰 계층 구조에서 더 상위 단계로 액세스해야 합니다. 이를 두 보기에서 호출할 수 있는 함수로 리팩터링하면 사용자 를 매개 변수로 사용하고 Realm.configuration을 반환합니다.

마지막으로 이 작업은 실제로 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 이후에 배경 작업의 실행을 오랫동안 지연시킬 수 있는 많은 다른 고려 사항들을 고려합니다. 장치가 배경 작업을 실행하여 원하는 작업을 수행하는지 기다리는 대신, 중단점을 설정하고 LLDB를 사용하여 작업을 호출할 수 있습니다

1

백그라운드 작업이 백그라운드에서 동기화된 Realm을 업데이트하는지 테스트하려면 최소 iOS 16 를 실행하는 물리적 장치가 필요합니다. 개발자 모드 에서 실행되도록 기기를 구성해야 합니다. . Untrusted Developer 알림을 받으면 Settings, GeneralVPN & Device Management로 Go 합니다. 여기에서 개발 중인 앱을 실행할 것인지 확인할 수 있습니다.

여러분의 장치에서 앱을 성공적으로 실행할 수 있으면 배경 작업을 테스트할 수 있습니다.

2

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
}
3

이제 연결된 장치에서 앱을 실행합니다. 앱에서 계정을 만들거나 로그인합니다. SwiftUI 템플릿 앱을 사용하는 경우, 몇 가지 항목을 만듭니다. 항목이 Atlas App Services 앱에 연결된 Item collection에 동기화되는 것을 볼 수 있습니다.

그런 다음 Xcode에서 앱을 실행 중인 상태에서 앱을 장치의 배경으로 보냅니다. 콘솔에 '배경 작업이 성공적으로 예약되었습니다'라고 출력되고 LLDB 프롬프트가 나타나야 합니다.

4

Xcode에서 앱이 배경에 있지만 여전히 실행 중일 때, 동기화되어야 할 관련 Atlas 컬렉션에 새 문서를 삽입하세요. 또는, 장치에서 생성한 기존 문서의 값을 변경하세요. 배경 작업이 성공적으로 실행된 후, 배경 프로세스에서 장치로 이 데이터가 동기화된 것을 볼 수 있어야 합니다.

SwiftUI 템플릿 앱을 사용하는 경우 Atlas cluster의 Item 컬렉션에서 관련 문서를 찾을 수 있습니다. Atlas에서 문서를 추가하거나 변경하는 방법에 대한 자세한 내용은 MongoDB Atlas: 문서 생성, 보기, 업데이트 및 삭제를 참조하세요.

5

이 명령을 사용하여 LLDB에서 배경 작업을 수동으로 실행할 수 있습니다:

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 버튼을 사용하여 앱 실행을 다시 시작합니다.

6

배경 작업이 완료될 때까지 기다린 후 앱을 다시 열기 전에 장치에서 비행기 모드를 켜십시오. Wi-Fi가 꺼져 있는지 확인합니다. 이렇게 하면 앱을 다시 열 때 새로운 동기화가 시작되지 않고 현재 장치의 Realm에 있는 값만 볼 수 있습니다.

7

디바이스에서 앱을 엽니다. Atlas에서 변경한 업데이트된 데이터를 확인할 수 있습니다.

배경 작업을 통해 업데이트가 이루어졌는지 확인하려면 네트워크를 성공적으로 비활성화했는지 확인하십시오.

앱을 사용하여 새 작업을 만듭니다. 앱에 작업이 표시되어야 하지만 Atlas와 동기화되어서는 안 됩니다. 또는 Atlas에서 데이터를 생성하거나 변경할 수 있지만 해당 데이터가 장치에 반영되어서는 안 됩니다.

이렇게 하면 네트워크가 성공적으로 비활성화되었으며, 표시되는 업데이트된 데이터는 배경 작업을 통해 가져온 것임을 알 수 있습니다.

돌아가기

동기화 오류 처리

다음

SwiftUI 미리 보기와 함께 Realm 사용