First, the introduction
Before IOS7, the system did not provide a complete framework to describe the functions associated with task progress. This makes it difficult to monitor the progress of time-consuming tasks in development, and after iOS7, the system provides a nsprogress class to specifically report on the progress of the task.
second, create a single task Progress listener
Single-Task progress monitoring is one of the simplest nsprogress scenarios where we use timers to simulate a time-consuming task with sample code as follows:
@interface Viewcontroller () {nsprogress * progress;} @end @implementation Viewcont
roller-(void) viewdidload {[Super viewdidload];
Do no additional setup after loading the view, typically from a nib.
This method creates a task progress management Object Unitcount is a number of units based on the complete task on the UI progress = [Nsprogress progresswithtotalunitcount:10]; Nstimer * timer = [Nstimer scheduledtimerwithtimeinterval:1 target:self selector: @selector (Task) Userinfo:nil repeats:
YES]; Monitor the completion ratio of task progress objects [Progress addobserver:self forkeypath:@ "fractioncompleted" options:nskeyvalueobservingoptionnew
Context:nil]; }-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary *) Change context: (void * Context {NSLog (@ "progress =%f", progress.fractioncompleted);}-(void) task{//Complete number of task units +1 if (PROGRESS.COMPLETEDUNITCOUNT&L
T;progress.totalunitcount) {Progress.completedunitcount +=1; }
}
In the example code above, the Fractioncompleted property is a floating-point value between 0-1 for the task's completion scale. The Nsprogress object also has two string-type properties that translate the progress information into a fixed format:
After display than for example: 10% completed
@property (null_resettable, copy) NSString *localizeddescription;
Completed quantity such as: 1
of @property (null_resettable, copy) NSString *localizedadditionaldescription;
Third, create a multitasking progress listener
This shows the progress monitoring method with only one task, in fact, in development, a task often has many subtasks, nsprogress is designed in a tree structure, which supports the nesting of subtasks, examples are as follows:
-(void) viewdidload {[Super viewdidload];
Do no additional setup after loading the view, typically from a nib.
This method creates a task progress management Object Unitcount is a number of units based on the complete task on the UI progress = [Nsprogress progresswithtotalunitcount:10]; Monitor the completion ratio of task progress objects [Progress addobserver:self forkeypath:@ "fractioncompleted" options:nskeyvalueobservingoptionnew
Context:nil];
Sub-expenditure sub-task the total number of subtasks is 5 units that is, when the subtask completes, the parent Progerss object progresses 5 units [progress Becomecurrentwithpendingunitcount:5];
[Self subtaskone];
[Progress Resigncurrent];
Sub-2nd subtask [Progress Becomecurrentwithpendingunitcount:5];
[Self subtaskone];
[Progress Resigncurrent];
}-(void) subtaskone{//Subtasks Total 10 units nsprogress * Sub =[nsprogress progresswithtotalunitcount:10];
int i=0;
while (i<10) {i++;
sub.completedunitcount++; }-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary *) Change context: (void
*) Context {NSLog (@ "=%@", progress.localizedadditionaldescription);}
The tree-like design pattern of nsprogress seems to be somewhat confusing at first glance, and one thing to note, Becomecurrentwithpendingunitcount: The meaning of the method is to register this Nsprogress object as the root progress management object for the current thread task, resigncurrent the method to unregister, the two methods must appear in pairs, and when a Nsprogress object is registered as the root node of the current thread, the following class method is used Progresswithtotalunitcount: The Nsprogress object that you create is added by default as a child node.
A new design method for multi-task progress monitoring after four-iOS9
As the example above shows, the way to register the root node is not very readable, the code structure is not very clear, perhaps Apple engineers also think so, after the iOS9, the Nsprogress class also added some methods, through these methods can more clearly express the hierarchy between the progress indicator, The sample code is as follows:
-(void) viewdidload {
[super viewdidload];
Do no additional setup after loading the view, typically from a nib.
This method creates a task progress management Object Unitcount is a number of units based on the complete task on the UI
progress = [nsprogress progresswithtotalunitcount:10];
Monitor the completion ratio of task progress objects
[Progress addobserver:self forkeypath:@ "fractioncompleted" options: Nskeyvalueobservingoptionnew Context:nil];
Create child Nodes
nsprogress * sub = [nsprogress progresswithtotalunitcount:10 parent:progress pendingunitcount:5];
nsprogress * Sub2 = [nsprogress progresswithtotalunitcount:10 parent:progress pendingunitcount:5];
for (int i=0; i<10; i++) {
sub.completedunitcount + +;
Sub2.completedunitcount + +;
}
}
As the code above shows, the structure of the code becomes clearer and more operable.
51 Little Summary
Gets the current thread's progress management object root node//Note: When a Nsprogress object invokes the Becomecurrentwithpendingunitcount: Method, this method obtains the + (nullable nsprogress *)
currentprogress;
Creates a Nsprogress object that requires the number of units to pass in the Progress + (Nsprogress *) Progresswithtotalunitcount: (int64_t) Unitcount;
And the previous method features similar iOS9 after the new method + (Nsprogress *) Discreteprogresswithtotalunitcount: (int64_t) Unitcount; The new method after iOS9 creates a child node of a progress indicator node + (nsprogress *) Progresswithtotalunitcount: (int64_t) Unitcount Parent: (nsprogress *)
Parent Pendingunitcount: (int64_t) Portionofparenttotalunitcount; The initialization method for the Nsprogress instance can be nil-(instancetype) initwithparent from the parent node parameter (nullable nsprogress *) Parentprogressornil UserInfo
:(Nullable nsdictionary *) Userinfoornil;
Register as current line Chenggen node-(void) Becomecurrentwithpendingunitcount: (int64_t) Unitcount;
Cancellation registration and registration methods must occur synchronously-(void) resigncurrent;
IOS9 The new method adds a child node-(void) AddChild: (Nsprogress *) to a node: (int64_t) Inunitcount;
The total number of progress units @property int64_t Totalunitcount;
The number of completed progress units @property int64_t Completedunitcount; Whether @property can be canceled (Getter=iscancellable) BOOL cancellable;
Whether @property (getter=ispausable) BOOL pausable can be suspended;
Progress ratio 0-1 @property (readonly) double fractioncompleted;
Cancel-(void) cancel;
Pause-(void) pause;
Recovery-(void) resume
Vi. User Configuration dictionaries for nsprogress objects
In the Nsprogress object's user dictionary, you can set some specific key values for display mode settings, as shown in the following example:
Setting the remaining time affects the value of localizedadditionaldescription/* For example: 0 of 10-about seconds remaining/[Progress setuserinfoobject:@1
0 Forkey:nsprogressestimatedtimeremainingkey]; Setting the completion speed information affects the value of localizedadditionaldescription/* For example: Zero KB of bytes (bytes/sec) */[Progress Setuserinfoobject:@15
Forkey:nsprogressthroughputkey]; /* The following key values are in effect must set the kind property of the Nsprogress object to the Nsprogresskindfile Nsprogressfileoperationkindkey key corresponds to the prompt text type The values that affect localizeddescription Nsprogressfileoperationkindkey optional corresponding values are as follows: nsprogressfileoperationkinddownloading:
Show downloading Files ...
Nsprogressfileoperationkinddecompressingafterdownloading: Show decompressing files ...
Nsprogressfileoperationkindreceiving: Show receiving files ... Nsprogressfileoperationkindcopying: Show Copying Files ... * * [Progress Setuserinfoobject:
Nsprogressfileoperationkinddownloading Forkey:nsprogressfileoperationkindkey]; /* Nsprogressfiletotalcountkey The total number of files displayed for example: Copying files ... * * [Progress setuserinfoobject:@100 Forkey:
Nsprogressfiletotalcountkey]; Set the completedQuantity [Progress setuserinfoobject:@1 forkey:nsprogressfilecompletedcountkey];
Summary of progress steps displayed in the UI
Here are a few steps to show progress in a view or a view controller:
1. Before you call a long-running task, use the +progresswithtotalunitcount:. method to establish a nsprogress instance. The parameter totalunitcount will include the "number of total work units to complete."
It is important to fully understand this value from the perspective of the UI layer; You will not be asked to guess how many actual work objects and how many kinds of work units (bytes) there are. Pixel? Number of lines of text? )。 If you traverse the collection and plan to call the instance object for each of the collection elements, the argument is often 1 or perhaps the number of elements in a collection.
2. Use KVO to register an observer of a progress fractioncompleted attribute. Similar to nsoperation,nsprogress is designed with the help of KVO. In Mac, this makes it very easy to bind a nsprogress instance via cocoa bindings to a progress bar or tag. On iOS, you will manually update your UI in the KVO observer handle.
In addition to the fractioncompleted, Completedunitcount, and Totalunitcount attributes, Nsprogress also has a localizeddescription (@ "50% completed"), There is also a localized Additional Description (@ "3 of 6") that can be bound to a text label. KVO notifications are sent in the thread that changes the property values of the Nsprogress object, so make sure that the UI is manually updated in your main thread.
3. The current progress object creates a new progress object by calling the-becomecurrentwithpendingunitcount: method. Here, Pendingunitcount this parameter is "part of the work to be done by the total number of work units to be completed by the receiver." You can call this method multiple times and pass a portion of the totalunitcount (the percentage of this code completion) each time. In the iteration example of the collection element, we will call [progress Becomecurrentwithpendingunitcount:1] in each iteration;
4. Methods to invoke the work object. Since the current progress is a local thread concept, you must do this in the same thread that you call Becomecurrentwithpendingunitcount:. If the API for the work object is designed to be invoked in the main thread, then this is not a problem, as I think of most APIs (as Brent Simmons does).
But if your UI layer is building a background queue and calling the work object to sync that queue, make sure that the Becomecurrentwithpendingunitcount: and Resigncurrent are placed in the same dispatch_async () Block is called in.
5. Call-resigncurrent in your progress object. This method corresponds to the-becomecurrentwith Pendingunitcount: and calls the same number of times. You can call Resigncurrent before the actual work is done, so you don't have to wait until you get a completion notice from the work object.