Open ClassFoundation5.9.0


    Progress is used to report the amount of work done, and provides a way to allow the user to cancel that work.

    class Progress

    Since work is often split up into several parts, progress objects can form a tree where children represent part of the overall total work. Each parent may have as many children as required, but each child only has one parent. The top level progress object in this tree is typically the one that you would display to a user. The leaf objects are updated as work completes, and the updates propagate up the tree.

    The work that a Progress does is tracked via a “unit count.” There are two unit count values: total and completed. In its leaf form, a Progress is created with a total unit count and its completed unit count is updated by setting completedUnitCount until it matches the totalUnitCount. The progress is then considered finished.

    When progress objects form nodes in trees, they are still created with a total unit count. Portions of the total are then handed out to children as a “pending unit count.” The total amount handed out to children should add up to the parent’s totalUnitCount. When those children become finished, the pending unit count assigned to that child is added to the parent’s completedUnitCount. Therefore, when all children are finished, the parent’s completedUnitCount is equal to its totalUnitCount and it becomes finished itself.

    Children Progress objects can be added implicitly or by calling addChild(withPendingUnitCount) on the parent. Implicitly added children are attached to a parent progress between a call to becomeCurrent(withPendingUnitCount) and a call to resignCurrent. The implicit child is created with the Progress(totalUnitCount:) initializer, or by passing the result of Progress.currentProgress to the Progress(parent:userInfo:) initializer. Both kinds of children can be attached to the same parent progress object. If you have an idea in advance that some portions of the work will take more or less time than the others, you can use different values of pending unit count for each child.

    If you are designing an interface of an object that reports progress, then the recommended approach is to vend a Progress property and adopt the ProgressReporting protocol. The progress should be created with the Progress.discreteProgress(withTotalUnitCount:) class function. You can then either update the progress object directly or set it up to have children of its own. Users of your object can compose your progress into their tree by using the addChild(withPendingUnitCount) function.

    If you want to provide progress reporting for a single method, then the recommended approach is to implicitly attach to a current Progress by creating an Progress object at the very beginning of your method using Progress(withTotalUnitCount). This progress object will consume the pending unit count, and then you can set up the progress object with children of its own.

    The localizedDescription and localizedAdditionalDescription properties are meant to be observed as well as set. So are the cancellable and pausable properties. totalUnitCount and completedUnitCount, on the other hand, are often not the best properties to observe when presenting progress to the user. You should observe fractionCompleted instead of observing totalUnitCount and completedUnitCount and doing your own calculation. Progress’ default implementation of fractionCompleted does fairly sophisticated things like taking child Progress into account.


    Citizens in Foundation