Created
July 6, 2018 16:15
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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