Progress indicators are seen everywhere in any systems such as loading webpages of browsers, installation of applications and reminding time and tasks for user completion. NSProgress
is class to accurate report the progress of work.
class NSProgress {
var totalUnitCount: Int64 //total work units
var completedUnitCount: Int64 //total work units completed
var fractionCompleted: Double { get } //computed property
var indeterminate: Bool { get } // return true if totalUnitCount < 0 or completedUnitCount < 0, useful when the total work unit is unknown
var localizedDescription: String!
var localizedAdditionalDescription: String!
var kind: NSProgressKind
}
currently only setting kind
as NSProgressKindFile
to change the localizedDescriptions
and localizedAdditionalDescription
Composition of progress is needed when not tracking single progress but many progress
Use a parent progress that allows childs' progress to report back via pendingUnitCount
In older system, implicit composition is used
let parentProgress = NSProgress()
parentProgress.totalUnitCount = 2
//assigning 1 unit count to child's progress to finish
parentProgress.becomeCurrentWithPendingUnitcount(1)
startDownload() //NSProgress(totalUnitCount:...)
parentProgress.resignCurrent() //completed child's progress
let childProgress = child.progress
let parentProgress = ...
parentProgress.addChild(childProgress, withPendingUnitCount:1)
var cancellable: Bool
var cancellationHandler: (() -> Void)?
var cancelled: Bool { get }
calling progress.cancel()
will
cancelled
to truecancellationHandler
var pausable: Bool
var pausingHandler: (() -> Void)?
var resumingHandler: (() -> Void)?
var paused: Bool { get }
calling progress.pause() or progress.resume()
will
NSProgress properties are key value observable
//somewhere in code
progress.addObserver(self, forKeyPath: "fractionCompleted", options: [], context: &observationContext)
override func observeValueForKeyPath(keyPath: ..., object: ..., ..., context: ...) {
if context == &observationContext && keyPath == "fractionCompleted" {
NSOperationQueue.mainQueue().addOperationWithBlock {
let progress = (object as! NSProgress)
progressView.progress = Float(progress.fractionCompleted)
}
}
else {
super.observeValueForKeyPath(...)
}
}