일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- swift database
- SeSAC
- KeyPath
- Combine
- Subject
- ios database
- swift db
- swift
- xcode
- GCD
- RxSwift
- Firebase
- arc
- Tuist Swift
- ios
- swift 5.9
- Tuist
- Subscribe
- Swift Tuist
- JSON
- observable
- swift 6
- realm
- ribs
- 카카오뱅크 ios
- SwiftUI
- 네트워크 통신
- Firebase Analytics
- swiftdata
- ios swiftdata
- Today
- Total
천원의 개발
iOS Background Tasks(백그라운드에서 API 호출하기) 본문
안녕하세요. 천원입니다.
백그라운드에서 API를 호출하기 위해서 학습한 내용을 정리 하고자 이글을 작성합니다.
Background Tasks 프레임워크
iOS 13부터 추가된 프레임워크로 시스템과 앱간의 background Task 요청을 담당하는 역할을 합니다.
해당 프레임워크에는 BGAppRefreshTask & BGProcessingTask 이렇게 두가지 타입이 존재하는데 BGAppRefreshTask는 30초 정도가 소요되는 작업에 사용되고 그 이상의 몇분이 소요되는 것들은 BGProcessingTask를 사용하게 됩니다.
WWDC 2019 자료를 참고해 보면 사용자가 Foreground로 진입하는 시점을 시스템이 분석해서 그전에 호출하게 되고 그 외에도 유저의 백그라운드 앱 새로고침 설정, 배터리 충전 상태, 네트워크 연결 등의 여부에 따라 호출하며 앱을 호출하는 정확한 시점은 파악할 수 없습니다.
구현해보기
먼저 Signing&Capabilities 에서 Background Modes를 추가해 주고, Background fetch와 Background processing을 체크해 줍니다. 각각 BGAppRefreshTask와 BGProcessingTask에 대한 설정입니다.
그 다음 스케줄러에 사용할 identifier를 Info.plist에 추가해 줍니다.
Permitted background task scheduler identifiers 을 추가해 주고 Item의 Value 에 String 타입으로 identifier를 작성해 줍니다.
다음으로 TasK를 AppDelegate의 didFinishLauchingWithOptions 함수에 등록해 줍니다.
각각의 핸들러 내부에는 실제로 수행할 백그라운드 동작을 구현해 주는데 이때 파라미터로 task를 함께 호출해 줍니다.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
BGTaskScheduler.shared.register(forTaskWithIdentifier: "example.com", using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask) // 실제로 수행할 코드가 구현된 매서드
}
// 2. Processing Task
BGTaskScheduler.shared.register(forTaskWithIdentifier: "example2.com", using: nil) { task in
self.handleProcessingTask(task: task as! BGProcessingTask)
}
return true
}
수행할 코드의 구현부를 간단하게 보자면 저는 로그를 기록할 파일을 만들어 백그라운드에서 호출될 때 파일에 기록되도록 코드를 작성했고, 함수 내부에서 setTaskCompleted(success: true)를 통해서 task의 성공여부를 반드시 호출해 주어야 합니다.
func handleAppRefresh(task: BGAppRefreshTask) {
self.writeLog(_writeValue: "백그라운드 호출 기록")
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
task.setTaskCompleted(success: true)
}
저는 BGProcessing Task를 사용하는 handleProcessingTask 함수 또한 동일한 코드로 구성하였습니다.
수행할 Task등록이 되었다면 우리는 Scene이 백그라운드에 진입할 때 해당 Task를 호출할 수 있도록 스케줄러를 등록해 줍니다.
등록시에 timeInterval을 설정할 수 있지만 원하는대로 동작하지 않습니다.
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "example.com") // 설정한 identifier
request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 60) // 호출할 timeInterval을 1시간으로 설정
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: \(error)")
}
}
func scheduleProcessingTaskIfNeeded() {
let request = BGProcessingTaskRequest(identifier: "example2.com")
request.requiresExternalPower = false // 에너지 소모량
request.requiresNetworkConnectivity = false // 네트워크 사용여부 옵션
request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 60)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("\(Date()): Could not schedule processing task: \(error)")
}
}
스케줄러를 등록하는 함수를 sceneDidEnterBackground 에서 호출해 줍니다.
func sceneDidEnterBackground(_ scene: UIScene) {
scheduleAppRefresh()
scheduleProcessingTaskIfNeeded()
}
테스트해 보기
이제 스케줄러까지 등록을 했으면 테스트를 진행해야 하지만 백그라운드에서 동작하기에 Xcode에서 테스트하기 쉽지 않습니다.
그러니 차근차근 진행해 봅시다.
앱을 실행 후 해당 지점에 브레이크 포인트를 걸어두고 백그라운드에 진입합니다.
그런다음 아래에 명령어를 lldb에 입력해 줍니다.
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"Info.plist에 등록한 태스크 Identifier"]
명령어가 실행되면 다시 포그라운드 진입 후 Continue 해주면 정상적으로 handleAppRefresh 함수를 호출하는 모습입니다.
아래는 기록된 백그라운드 호출 로그입니다.
출처:
'iOS&Swift🍎 > iOS' 카테고리의 다른 글
iOS SwiftData CRUD를 구현해보자 (0) | 2024.08.22 |
---|---|
iOS KeyPath 정리 (1) | 2023.12.26 |
iOS Continuation 정리 (0) | 2023.11.24 |
iOS Tuist 적용하여 여러 프로젝트 관리하기 (0) | 2023.10.24 |
iOS Preview 보면서 codebase로 작업하기 (0) | 2023.07.12 |