develop
BackgroundFetch 앱 백그라운드 상태에서 로직 실행하기 본문
반응형
iOS 앱에서 App LifeCycle이 applicationDidEnterBackground가 되면 로직이 실행이 되지 않는다.
대용량 파일을 다운로드, 업로드할때 앱화면에서 배경화면으로 들어갔을떄 다운로드, 업로드가 중단되어진다.
사용자들은 다운로드, 업로드할때 계속 앱을 열어야 하지만 BackgroundFetch기능으로 applicationDidEnterBackground가 되어도 로직이 계속 실행되게 할 수 있다.
BackgroundTask 상태를 알려준다.
var backgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid
UIBackgroundTaskIdentifier는 이렇게 구현되어 있다.
public struct UIBackgroundTaskIdentifier : Hashable, Equatable, RawRepresentable {
public init(rawValue: Int)
}
extension UIBackgroundTaskIdentifier {
@available(iOS 4.0, *)
public static let invalid: UIBackgroundTaskIdentifier
}
BackgroundTask를 시작한다.
backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask {
}
BackgroundTask를 종료한다.
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
Identifier을 받고 작업을 하다가 종료하는 코드를 만들어 보았다.
class BackgroundFetch: NSObject {
static let shared = BackgroundFetch()
private var backgroundTaskIdentifiers = [UIBackgroundTaskIdentifier]()
func beginBackgroundTask(_ callback: (UIBackgroundTaskIdentifier) -> Void) {
var backgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid
backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask { [weak self] in
self?.endBackgroundTask(identifier: backgroundTaskIdentifier)
}
self.backgroundTaskIdentifiers.append(backgroundTaskIdentifier)
callback(backgroundTaskIdentifier)
}
func endAllBackgroundTask() {
let identifiers = self.backgroundTaskIdentifiers
self.backgroundTaskIdentifiers.removeAll()
identifiers.forEach({ UIApplication.shared.endBackgroundTask($0) })
}
func endBackgroundTask(identifier: UIBackgroundTaskIdentifier) {
if let index = self.backgroundTaskIdentifiers.firstIndex(where: { $0 == identifier }) {
self.backgroundTaskIdentifiers.remove(at: index)
}
UIApplication.shared.endBackgroundTask(identifier)
}
}
extension UIBackgroundTaskIdentifier {
func endBackgroundTask() {
BackgroundFetch.shared.endBackgroundTask(identifier: self)
}
}
이렇게 사용 가능하다.
BackgroundFetch.shared.beginBackgroundTask { (identifier) in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print("Some Task...")
identifier.endBackgroundTask()
// BackgroundFetch.shared.endBackgroundTask(identifier: identifier)
print("Task Complete")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
print("Task Complete After")
}
}
}
Some Task...
Task Complete
아직 Foreground 상황이 안나와서 Task Complete After는 호출이 안되었다.
앱을 다시 열면 Task Complete After가 콘솔창에 나온다.
여러개의 파일을 업로드, 다운로드 같이 할 경우이다.
BackgroundFetch.shared.beginBackgroundTask { (identifier) in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print("Some Task...")
identifier.endBackgroundTask()
// BackgroundFetch.shared.endBackgroundTask(identifier: identifier)
print("Task Complete")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
print("Task Complete After")
}
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
BackgroundFetch.shared.beginBackgroundTask { (identifier) in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print("Some Task2...")
identifier.endBackgroundTask()
print("Task2 Complete")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
print("Task2 Complete After")
}
}
}
}
Some Task...
Task Complete
Some Task2...
Task2 Complete
Task Complete After
아직 Foreground 상황이 안나와서 Task2 Complete After는 호출이 안되었다.
앱을 다시 열면 Task2 Complete After가 콘솔창에 나온다.
반응형
'iOS' 카테고리의 다른 글
Struct initialization (0) | 2021.01.26 |
---|---|
autoreleasepool (0) | 2021.01.25 |
Cache 앱의 캐시 사용하기 (0) | 2021.01.23 |
Generic (0) | 2021.01.21 |
Throttle, Debounce (0) | 2021.01.20 |
Comments