NSProgress Class Reference

Inherits from
Conforms to
Framework
/System/Library/Frameworks/Foundation.framework
Availability
Available in iOS 7.0 and later.
Declared in
NSProgress.h

Overview

The NSProgress class provides a self-contained mechanism for progress reporting. It makes it easy for code that does work to report the progress of that work, and for user interface code to observe that progress for presentation to the user. Specifically, it can be used to show the user a progress bar and explanatory text, both updated properly as progress is made. It also allows work to be cancelled or paused by the user.

Reporting Progress

Using the methods of this class, your code can report the progress it’s currently making toward completing some task, including progress in related subtasks. You can create instances of this class using the initWithParent:userInfo: instance method or the progressWithTotalUnitCount: class method.

Progress objects have a number of properties that you can use to observe and report current progress. For instance, the totalUnitCount property represents the total number of units of work that need to be performed, and the completedUnitCount and fractionCompleted properties represents how much of that work has already been completed. The fractionCompleted property is useful for updating progress indicators or textual descriptors; to check whether progress is complete, you should test that completedUnitCount >= totalUnitCount (assuming, of course, that totalUnitCount > 0).

The following listing shows a sample method that reports the progress of performing some operation on a piece of data. When the progress object is first created, the value of its totalUnitCount property is set to some suitable batch size for this operation, and the completedUnitCount count is 0. Each time the loop executes and the batch of data is processed, the progress object’s totalUnitCount property is incremented appropriately.

- (void)startTaskWithData:(NSData *)data {
    NSUInteger batchSize = ... use a suitable batch size
    NSProgress *progress = [NSProgress progressWithTotalUnitCount:batchSize];
 
    for (NSUInteger index = 0; index < batchSize; index++) {
        // Check for cancellation
        if ([progress isCancelled]) {
             // Tidy up as necessary...
             break;
        }
 
        // Do something with this batch of data...
 
        // Report progress (add 1 because we've completed the work for the current index).
        [progress setCompletedUnitCount:(index + 1)];
    }
}

Each of the properties of a progress object, including totalUnitCount, completedUnitCount, and fractionCompleted, support Key-Value Observing. This makes it extremely easy for a view or window controller object to observe the properties, and update UI elements such as progress indicators when the values change. It also means that there is a non-zero cost to updating the values of these properties, so you should avoid using a unit count that is too granular—if you’re iterating over a large data set, for example, and each operation takes only a trivial amount of time, you should divide the work into batches so you can update the unit count once per batch rather than once per iteration.

Creating a Tree of Progress Objects

Often, your code may need to report the overall progress of an operation that is composed of several suboperations. To accomplish this, your code can report the progress of each suboperation by building up a tree of progress objects.

The NSProgress reporting mechanism supports a loosely coupled relationship between progress objects. Suboperations don’t need to know anything about the parent progress item—you can simply create new progress objects and, if another NSProgress instance already exists and is marked as being current for the current thread, the new objects will be set as children of that instance. When the children complete, the parent’s completedUnitCount property is automatically increased by a predefined amount.

As an example, consider that you are tracking the progress of code downloading and copying files on disk. You could use a single progress object to track the entire task, but it’s easier to manage each subtask using a separate progress object. You start by creating an overall parent progress object with a suitable total unit count, then call becomeCurrentWithPendingUnitCount:, then create your sub-task progress objects, before finally calling resignCurrent.

The pending unit count that you specify in the first method is divided equally among the child progress objects you create between these two method calls. Each child progress object maintains its own internal unit count, but when it completes its units (that is, the child object’s completedUnitCount == totalUnitCount), the parent progress object’s completedUnitCount is increased by the assigned portion of the original pending unit count.

In the following example, the overall parent progress has 100 units; the two child objects therefore get 50 pending units each, and keep track internally of 10 units of work each. When each child completes its 10 units, the parent’s completed unit count is increased by 50.

- (void)startLongOperation {
    self.overallProgress = [NSProgress progressWithTotalUnitCount:100];
 
    [self.overallProgress becomeCurrentWithPendingUnitCount:50];
    [self work1];
    [self.overallProgress resignCurrent];
 
    [self.overallProgress becomeCurrentWithPendingUnitCount:50];
    [self work2];
    [self.overallProgress resignCurrent];
}
 
- (void)work1 {
    NSProgress *firstTaskProgress = [NSProgress progressWithTotalUnitCount:10];
    // Perform first task...
}
 
- (void)work2 {
    NSProgress *secondTaskProgress = [NSProgress progressWithTotalUnitCount:10];
    // Perform second task...
}

If you don’t create any child progress objects between the calls to becomeCurrentWithPendingUnitCount: and resignCurrent, the “parent” progress automatically updates its completedUnitCount by adding the pending units.

Tasks

Creating Progress Objects

Current Progress Object

Reporting Progress

Observing Progress

Controlling Progress

Progress Information

Properties

cancellable

Indicates whether the receiver is tracking work that can be cancelled.

@property(getter=isCancellable) BOOL cancellable
Discussion

By default, NSProgress objects are cancellable.

You typically use this property to communicate whether controls for canceling should appear in a progress reporting user interface. NSProgress itself does not do anything with this property other than help pass the value from progress reporters to progress observers.

If an NSProgress is cancellable, you should implement cancelability either by setting a block for the cancellationHandler property, or by polling the cancelled property periodically while performing the relevant work.

It is valid for the value of this property to change during the lifetime of an NSProgress object. By default, NSProgress is KVO-compliant for this property, sending notifications on the same thread that updates the property.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

cancellationHandler

The block to invoke when progress is cancelled.

@property(copy) void (^cancellationHandler)(void)
Discussion

If the receiver is a child of another progress object, the cancellationHandler block will be invoked when the parent is cancelled.

Special Considerations

The cancellation handler may be invoked on any queue. If you must do work on a specific queue, you should dispatch to that queue from within the cancellation handler block.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

cancelled

Indicates whether the receiver is tracking work that has been cancelled. (read-only)

@property(readonly, getter=isCancelled) BOOL cancelled
Discussion

By default, NSProgress is KVO-compliant for this property, sending notifications on the same thread that updates the property.

If the receiver has a parent that has already been cancelled, the receiver will also report being cancelled.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

completedUnitCount

The number of units of work for the current job that have already been completed.

@property int64_t completedUnitCount
Discussion

For an NSProgress with a kind of NSProgressKindFile, the unit of this property is bytes while the NSProgressFileTotalCountKey and NSProgressFileCompletedCountKey keys in the userInfo dictionary are used for the overall count of files.

For any other kind of NSProgress, the unit of measurement does not matter as long as it is consistent. The values may be reported to the user in the localizedDescription and localizedAdditionalDescription.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

fractionCompleted

The fraction of the overall work completed by this progress object, including work done by any children it may have. (read-only)

@property(readonly) double fractionCompleted
Discussion

If the receiver object does not have any children, fractionCompleted is generally the result of dividing completedUnitCount by totalUnitCount.

If the receiver does have children, fractionCompleted will reflect progress made in child objects in addition to its own completedUnitCount. When children finish, the completedUnitCount of the parent is updated.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

indeterminate

Indicates whether the tracked progress is indeterminate. (read-only)

@property(readonly, getter=isIndeterminate) BOOL indeterminate
Discussion

Progress is indeterminate when the value of either totalUnitCount or completedUnitCount is less than zero.

Setting both totalUnitCount and completedUnitCount properties to zero indicates that there is no progress to track; in this case, isIndeterminate returns NO and fractionCompleted returns 1.0.

By default, NSProgress is KVO-compliant for this property, sending notifications on the same thread that updates the property.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

kind

A string identifying the kind of progress being made.

@property(copy) NSString *kind
Discussion

This property identifies the kind of progress being made, such as NSProgressKindFile. It can be nil.

If the value of the localizedDescription property has not previously been set to a non-nil value, the default localizedDescription getter uses the progress kind to determine how to use the values of other properties, as well as values in the user info dictionary, to create a string that is presentable to the user.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

localizedAdditionalDescription

A more specific localized description of progress tracked by the receiver.

@property(copy) NSString *localizedAdditionalDescription
Discussion

If you don’t specify your own custom value for this property, NSProgress uses the value of the kind property to determine how to use the values of other properties, as well as values in the user info dictionary, to return an automatically-computed string. If it fails to do that, it returns an empty string.

The localizedAdditionalDescription is more specific than localizedDescription about the work the receiver is tracking at any particular moment. Depending on the kind of progress, the completed and total unit counts, and other parameters, example localized additional descriptions include:

  • 3 of 10 files

  • 123 KB of 789.1 MB

  • 3.3 MB of 103.92 GB – 2 minutes remaining

  • 1.61 GB of 3.22 GB (2 KB/sec) – 2 minutes remaining

  • 1 minute remaining (1 KB/sec)

By default, NSProgress is KVO-compliant for this property, sending notifications on the same thread that updates the property.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

localizedDescription

A localized description of progress tracked by the receiver.

@property(copy) NSString *localizedDescription
Discussion

If you don’t specify your own custom value for this property, NSProgress uses the value of the kind property to determine how to use the values of other properties, as well as values in the user info dictionary, to return an automatically-computed string. If it fails to do that, it returns an empty string.

The localizedDescription represents a general description of the work tracked by the receiver. Depending on the kind of progress, the completed and total unit counts, and other parameters, example localized descriptions include:

  • Copying 10 files…

  • 30% completed

  • Copying “TextEdit”…

By default, NSProgress is KVO-compliant for this property, sending notifications on the same thread that updates the property.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

pausable

Indicates whether the receiver is tracking work that can be paused.

@property(getter=isPausable) BOOL pausable
Discussion

By default, NSProgress objects are not pausable.

You typically use this property to communicate whether controls for pausing should appear in a progress reporting user interface. NSProgress itself does not do anything with this property other than help pass the value from progress reporters to progress observers.

If an NSProgress is pausable, you should implement pausability either by setting a block for the pausingHandler property, or by polling the paused property periodically while performing the relevant work.

It is valid for the value of this property to change during the lifetime of an NSProgress object. By default, NSProgress is KVO-compliant for this property, sending notifications on the same thread that updates the property.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

paused

Indicates whether the receiver is tracking work that has been paused. (read-only)

@property(readonly, getter=isPaused) BOOL paused
Discussion

By default, NSProgress is KVO-compliant for this property, sending notifications on the same thread that updates the property.

If the receiver has a parent that has already been paused, the receiver will also report being paused.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

pausingHandler

The block to invoke when progress is paused.

@property(copy) void (^pausingHandler)(void)
Discussion

If the receiver is a child of another progress object, the pausingHandler block will be invoked when the parent is paused.

Special Considerations

The pausing handler may be invoked on any queue. If you must do work on a specific queue, you should dispatch to that queue from within the pausing handler block.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

totalUnitCount

The total number of units of work tracked for the current progress.

@property int64_t totalUnitCount
Discussion

For an NSProgress with a kind of NSProgressKindFile, the unit of this property is bytes while the NSProgressFileTotalCountKey and NSProgressFileCompletedCountKey keys in the userInfo dictionary are used for the overall count of files.

For any other kind of NSProgress, the unit of measurement does not matter as long as it is consistent. The values may be reported to the user in the localizedDescription and localizedAdditionalDescription.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

Class Methods

currentProgress

Returns the NSProgress instance, if any, associated with the current thread by a previous invocation of becomeCurrentWithPendingUnitCount:.

+ (NSProgress *)currentProgress
Return Value

The NSProgress instance associated with the current thread, if any.

Discussion

Use this per-thread currentProgress value to allow code that performs work to report useful progress even when it is widely separated from the code that actually presents progress information to the user, without requiring layers of intervening code to pass around an NSProgress instance.

When reporting progress, you typically work with a child progress object, created by calling progressWithTotalUnitCount:, to ensure that you report progress in known units of work.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

progressWithTotalUnitCount:

Creates and returns an NSProgress instance, initialized using initWithParent:userInfo:.

+ (NSProgress *)progressWithTotalUnitCount:(int64_t)unitCount
Parameters
unitCount

The total number of units of work to be carried out.

Discussion

The initializer is passed the current progress object, if there is one, and the value of the totalUnitCount property is set.

In many cases you can simply precede code that does a substantial amount of work with an invocation of this method, then repeatedly set the completedUnitCount or cancelled property in the loop that does the work.

You can invoke this method on one thread and then message the returned NSProgress on another thread. For example, you can capture the created progress instance in a block that you pass to dispatch_async(3) Mac OS X Developer Tools Manual Page. In that block you can invoke methods like becomeCurrentWithPendingUnitCount: or resignCurrent, and set the completedUnitCount or cancelled properties as work is carried out.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

Instance Methods

becomeCurrentWithPendingUnitCount:

Sets the receiver as the current progress object of the current thread and specifies the portion of work to be performed by the next child progress object of the receiver.

- (void)becomeCurrentWithPendingUnitCount:(int64_t)unitCount
Parameters
unitCount

The number of units of work to be carried out by the next progress object that is initialized by invoking the initWithParent:userInfo: method in the current thread with the receiver set as the parent. This number represents the portion of work to be performed in relation to the total number of units of work to be performed by the receiver (represented by the value of the receiver’s totalUnitCount property). The units of work represented by this parameter must be the same units of work that are used in the receiver’s totalUnitCount property.

Discussion

Use this method to build a tree of progress objects, as described in “Creating a Tree of Progress Objects.”

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

cancel

Cancel progress tracking.

- (void)cancel
Discussion

This method invokes the block set for cancellationHandler, if there is one, and ensures that any subsequent reads of the cancelled property return YES.

If the receiver has any children, those children will also be cancelled.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

initWithParent:userInfo:

Initializes a newly allocated NSProgress instance.

- (instancetype)initWithParent:(NSProgress *)parentProgressOrNil userInfo:(NSDictionary *)userInfoOrNil
Parameters
parentProgressOrNil

The parent NSProgress object, if any, to notify when reporting progress or to consult when checking for cancellation.

The only valid values are [NSProgress currentProgress] or nil.

userInfoOrNil

The user information dictionary for the progress object. May be nil.

Discussion

This is the designated initializer for the NSProgress class.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

pause

Pause progress tracking.

- (void)pause
Discussion

This method invokes the block set for pausingHandler, if there is one, and ensures that any subsequent reads of the paused property return YES.

If the receiver has any children, those children will also be paused.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

resignCurrent

Balance the most recent previous invocation of becomeCurrentWithPendingUnitCount: on the same thread by restoring the current progress object to what it was before becomeCurrentWithPendingUnitCount: was invoked.

- (void)resignCurrent
Discussion

Use this method after building your tree of progress objects, as described in “Creating a Tree of Progress Objects.”

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

setUserInfoObject:forKey:

Set a value in the userInfo dictionary.

- (void)setUserInfoObject:(id)objectOrNil forKey:(NSString *)key
Parameters
objectOrNil

The object to set for the given key, or nil to remove an existing entry in the dictionary.

key

The key to use to store the given object.

Discussion

Use this method to set a value in the userInfo dictionary, with appropriate KVO notification for properties whose values can depend on values in the user info dictionary, like localizedDescription.

Supply a value of nil to remove an existing dictionary entry for a given key.

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

userInfo

A dictionary of arbitrary values associated with the receiver.

- (NSDictionary *)userInfo
Return Value

A a KVO-compliant dictionary that changes in response to setUserInfoObject:forKey:.

Discussion

The dictionary sends all of its KVO notifications on the thread that updates the property.

Some entries have meanings that are recognized by the NSProgress class itself—see “General progress user info dictionary keys,” “Progress kinds,” “File operation user info dictionary keys,” and “File operation kinds.”

Availability
  • Available in iOS 7.0 and later.
Declared In
NSProgress.h

Constants

General progress user info dictionary keys

Set values for these keys in the user info dictionary to affect the auto-generated localizedAdditionalDescription string.

NSString *const NSProgressEstimatedTimeRemainingKey;
NSString *const NSProgressThroughputKey;
Constants
NSProgressEstimatedTimeRemainingKey

The corresponding value is an NSNumber instance representing the time remaining, in seconds.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

NSProgressThroughputKey

The corresponding value is an NSNumber instance indicating the speed of data processing, in bytes per second.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

Progress kinds

When working with files, set this string for the kind of progress.

NSString *const NSProgressKindFile;
Constants
NSProgressKindFile

The value for the kind property that indicates that the progress is tracking a file operation. If you set this value for the progress kind, you must set a value in the user info dictionary for the NSProgressFileOperationKindKey.

NSProgress of this kind is assumed to use bytes as the unit of work being done, and the default implementation of localizedDescription takes advantage of that to return more specific text than it could otherwise. The NSProgressFileTotalCountKey and NSProgressFileCompletedCountKey keys in the userInfo dictionary are used for the overall count of files.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

File operation user info dictionary keys

Set values for these keys in the user info dictionary to provide more information about file operations for the auto-generated localizedDescription and localizedAdditionalDescription strings.

NSString *const NSProgressFileOperationKindKey;
NSString *const NSProgressFileTotalCountKey;
NSString *const NSProgressFileCompletedCountKey;
Constants
NSProgressFileOperationKindKey

A value is required for this key in the user info dictionary when the progress kind is set to NSProgressKindFile. The corresponding value must be one of the entries listed in “File operation kinds”.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

NSProgressFileTotalCountKey

The corresponding value must be an NSNumber containing an integer to represent the total number of files affected. This entry is optional; if you set a value for this key, the auto-generated localizedAdditionalDescription string will make use of it.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

NSProgressFileCompletedCountKey

The corresponding value must be an NSNumber containing an integer to represent the number of completed files. This entry is optional; if you set a value for this key, the auto-generated localizedAdditionalDescription string will make use of it.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

File operation kinds

When tracking file operations with the progress kind set to NSProgressKindFile, you must provide a value for the NSProgressFileOperationKindKey in the user info dictionary. There are four possible values.

NSString *const NSProgressFileOperationKindDownloading;
NSString *const NSProgressFileOperationKindDecompressingAfterDownloading;
NSString *const NSProgressFileOperationKindReceiving;
NSString *const NSProgressFileOperationKindCopying;
Constants
NSProgressFileOperationKindDownloading

The progress is tracking a file download operation.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

NSProgressFileOperationKindDecompressingAfterDownloading

The progress is tracking file decompression after a download.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

NSProgressFileOperationKindReceiving

The progress is tracking the receipt of a file from another source.

Available in iOS 7.0 and later.

Declared in NSProgress.h.

NSProgressFileOperationKindCopying

The progress is tracking the copying of a file from source to destination.

Available in iOS 7.0 and later.

Declared in NSProgress.h.