Skip to content

Instantly share code, notes, and snippets.

@SpectralDragon
Created July 6, 2018 16:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SpectralDragon/061d3a7d4add7b2f397e504f61dec3cb to your computer and use it in GitHub Desktop.
Save SpectralDragon/061d3a7d4add7b2f397e504f61dec3cb to your computer and use it in GitHub Desktop.
Little solution for manage child progresses. Support Adding and Removing children and update totalUnitCount.
final class CompoundProgress: Progress {
private struct Child {
let progress: Progress
let cancellationObservation: NSKeyValueObservation
let completedUnitObservation: NSKeyValueObservation
func invalidate() {
self.cancellationObservation.invalidate()
self.completedUnitObservation.invalidate()
}
}
override var fractionCompleted: Double {
return children.map { $0.progress.fractionCompleted }.reduce(0, +) / Double(self.children.count)
}
private var children: [Child] = []
func removeChild(_ child: Progress) {
guard let index = self.children.index(where: { $0.progress == child }) else { return }
willChangeValue(for: \.fractionCompleted)
willChangeValue(for: \.completedUnitCount)
willChangeValue(for: \.totalUnitCount)
self.totalUnitCount -= child.totalUnitCount
self.completedUnitCount -= child.completedUnitCount
self.children.remove(at: index).invalidate()
didChangeValue(for: \.totalUnitCount)
didChangeValue(for: \.completedUnitCount)
didChangeValue(for: \.fractionCompleted)
}
override func addChild(_ childProgress: Progress, withPendingUnitCount inUnitCount: Int64) {
willChangeValue(for: \.totalUnitCount)
self.totalUnitCount += inUnitCount
didChangeValue(for: \.totalUnitCount)
let child = Child(progress: childProgress,
cancellationObservation: childProgress.observe(\.completedUnitCount, options: [.new, .old]) { [weak self] (progress, value) in
guard let oldCompletedUnitCount = value.oldValue, let newCompletedUnitCount = value.newValue else { return }
self?.completedUnitCount += newCompletedUnitCount - oldCompletedUnitCount
},
completedUnitObservation: childProgress.observe(\.isCancelled) { [weak self] (progress, _) in
guard progress.isCancelled else { return }
self?.removeChild(progress)
})
children.append(child)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment