여기와 다른 SO 질문에 대한 답변에서 언급했듯이 beginBackgroundTask
앱이 백그라운드로 전환 될 때만 사용하고 싶지는 않습니다 . 반대로, 당신을 위해 백그라운드 작업을 사용해야합니다 어느 누구의 완료하면 앱이 경우에도 보장하려면 시간이 많이 걸리는 작업 않는 배경으로 이동합니다.
따라서 코드는 호출 beginBackgroundTask
및 endBackgroundTask
일관성을 위해 동일한 상용구 코드의 반복으로 끝날 수 있습니다. 이러한 반복을 방지하려면 상용구를 캡슐화 된 단일 엔티티로 패키지화하는 것이 합리적입니다.
이를 수행하는 기존 답변 중 일부가 마음에 들지만 가장 좋은 방법은 Operation 하위 클래스를 사용하는 것입니다.
작업을 모든 OperationQueue에 대기열에 추가하고 적절하다고 판단되는대로 해당 대기열을 조작 할 수 있습니다. 예를 들어 큐에있는 기존 작업을 미리 취소 할 수 있습니다.
수행 할 작업이 두 개 이상인 경우 여러 백그라운드 작업 작업을 연결할 수 있습니다. 작업은 종속성을 지원합니다.
작업 대기열은 백그라운드 대기열이 될 수 있으며 그래야합니다. 따라서 작업 이 비동기 코드 이기 때문에 작업 내에서 비동기 코드를 수행하는 것에 대해 걱정할 필요가 없습니다 . (사실, 작업 내에서 다른 수준의 비동기 코드 를 실행하는 것은 이치 에 맞지 않습니다. 해당 코드가 시작되기 전에 작업이 완료되기 때문입니다.이 작업을 수행해야하는 경우 다른 작업을 사용합니다.)
다음은 가능한 Operation 하위 클래스입니다.
class BackgroundTaskOperation: Operation {
var whatToDo : (() -> ())?
var cleanup : (() -> ())?
override func main() {
guard !self.isCancelled else { return }
guard let whatToDo = self.whatToDo else { return }
var bti : UIBackgroundTaskIdentifier = .invalid
bti = UIApplication.shared.beginBackgroundTask {
self.cleanup?()
self.cancel()
UIApplication.shared.endBackgroundTask(bti) // cancellation
}
guard bti != .invalid else { return }
whatToDo()
guard !self.isCancelled else { return }
UIApplication.shared.endBackgroundTask(bti) // completion
}
}
이것을 사용하는 방법은 분명해야하지만 그렇지 않은 경우 전역 OperationQueue가 있다고 상상해보십시오.
let backgroundTaskQueue : OperationQueue = {
let q = OperationQueue()
q.maxConcurrentOperationCount = 1
return q
}()
따라서 일반적인 시간 소모적 인 코드 배치의 경우 다음과 같이 말할 수 있습니다.
let task = BackgroundTaskOperation()
task.whatToDo = {
// do something here
}
backgroundTaskQueue.addOperation(task)
시간이 많이 걸리는 코드 배치를 여러 단계로 나눌 수있는 경우 작업이 취소되면 조기에 작업을 중단하는 것이 좋습니다. 이 경우 폐쇄에서 조기에 반환하십시오. 클로저 내에서 작업에 대한 참조가 약해야합니다. 그렇지 않으면 유지주기가 발생합니다. 다음은 인공적인 그림입니다.
let task = BackgroundTaskOperation()
task.whatToDo = { [weak task] in
guard let task = task else {return}
for i in 1...10000 {
guard !task.isCancelled else {return}
for j in 1...150000 {
let k = i*j
}
}
}
backgroundTaskQueue.addOperation(task)
백그라운드 작업 자체가 조기에 취소 된 경우 정리해야 할 경우를 대비하여 선택적 cleanup
처리기 속성 (이전 예제에서는 사용되지 않음)을 제공했습니다. 다른 답변은 그것을 포함하지 않은 것에 대해 비판을 받았습니다.