Say I have some hierarchy of NSProgress
objects. For simplicity say a root progress with 2 children. If progress has already started can I add another child progress to the hierarchy and expect the right thing to happen? For example, say I start with 2 children, so the totalUnitCount
of the root is 2
and the pendingUnitCount
is 2
. Once the first child is complete the root progress' fractionCompleted
will be 0.5
. If I then add another child progress the root progress' fractionCompleted
does update to ~0.33
as I would like but the root's totalUnitCount
remains at 2
, as does the pendingUnitCount
. I can update the totalUnitCount
manually but this throws the root's fractionCompleted
off. Also, there seems to be no way to update the pendingUnitCount
without calling becomeCurrentWithPendingUnitCount:
. Was NSProgress
not designed for this kind of use or is there a "proper" way to do this?
My use case is that I have an application that can upload files to a remote server. The user may select some files and hit a button to start uploading them. While they are uploading the user sees the overall progress of the upload job. Now, if the user wants to select some more photos to upload while the uploads are already in progress I want to update the progress to reflect the new total. For example, he is currently uploading 2 files, 1 has already completed, while they are uploading he adds 2 more to upload. The progress should adjust itself. Total unit count should now be 4 and there should be 3 items remaining to upload. Seems like this would be a common use case to me.
Here's a unit test I wrote to play with dynamically extending an NSProgress
hierarchy. All the asserts in the test below pass but if you check the root's totalUnitCount
it always remains 2 and there seems to be no way to tell how many items remain to be completed from the root progress. The root progress is the one that the UI would observe so it is important that changes deeper in the hierarchy propagate up, including totalUnitCount
, etc.
- (void)testDynamicNSProgress
{
NSProgress *root = [NSProgress progressWithTotalUnitCount:2];
[root becomeCurrentWithPendingUnitCount:2];
NSProgress *child1 = [NSProgress progressWithTotalUnitCount:1];
NSProgress *child2 = [NSProgress progressWithTotalUnitCount:1];
XCTAssertEqual(root.totalUnitCount, 2);
XCTAssertEqual(root.completedUnitCount, 0);
child1.completedUnitCount++;
XCTAssertEqual(ceil(root.fractionCompleted * 100), 50);
NSProgress *child3 = [NSProgress progressWithTotalUnitCount:1];
NSProgress *child4 = [NSProgress progressWithTotalUnitCount:1];
XCTAssertEqual(ceil(root.fractionCompleted * 100), 25);
child2.completedUnitCount++;
XCTAssertEqual(ceil(root.fractionCompleted * 100), 50);
child3.completedUnitCount++;
XCTAssertEqual(ceil(root.fractionCompleted * 100), 75);
child4.completedUnitCount++;
XCTAssertEqual(ceil(root.fractionCompleted * 100), 100);
__unused NSProgress *child5 = [NSProgress progressWithTotalUnitCount:1];
XCTAssertEqual(ceil(root.fractionCompleted * 100), 80);
}
NSProgress
object. The overall progress reported okay up the hierarchy, but the total number of units at the root isn't changed unless you manually change it, as far as I can tell (NSProgress
'stotalUnitCount
property is mutable, so I was just doingparentProgress.totalUnitCount += <whatever>;
whenever I was about tobecomeCurrentWithPendingUnitCount
for the next task.) – Manama