iOS進度指示器——NSProgress

iOS進度指示器——NSProgress

1、引言

        在iOS7以前,系統一直沒有提供一個完整的框架來描述任務進度相關的功能。這使得在開發中進行耗時任務進度的監聽將什麼麻煩,在iOS7以後,系統提供了NSProgress類來專門報告任務進度。javascript

2、建立單任務進度監聽器

        單任務進度的監聽是NSProgress最簡單的一種運用場景,咱們來用定時器模擬一個耗時任務,示例代碼以下:java

@interface ViewController ()
{
    NSProgress * progress;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //這個方法將建立任務進度管理對象 UnitCount是一個基於UI上的完整任務的單元數
    progress = [NSProgress progressWithTotalUnitCount:10];
    NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(task) userInfo:nil repeats:YES];
    //對任務進度對象的完成比例進行監聽
    [progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{
    NSLog(@"進度= %f",progress.fractionCompleted);
}
-(void)task{
   //完成任務單元數+1
    
    if (progress.completedUnitCount<progress.totalUnitCount) {
        progress.completedUnitCount +=1;
    }
    
}

上面的示例代碼中,fractionCompleted屬性爲0-1之間的浮點值,爲任務的完成比例。NSProgress對象中還有兩個字符串類型的屬性,這兩個屬性將進度信息轉化成固定的格式:設計模式

//顯示完後比例 如:10% completed
@property (null_resettable, copy) NSString *localizedDescription;
//完成數量 如:1 of 10
@property (null_resettable, copy) NSString *localizedAdditionalDescription;

3、建立多任務進度監聽器

        上面演示了只有一個任務時的進度監聽方法,實際上,在開發中,一個任務中每每又有許多子任務,NSProgress是以樹狀的結構進行設計的,其支持子任務的嵌套,示例以下:框架

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //這個方法將建立任務進度管理對象 UnitCount是一個基於UI上的完整任務的單元數
    progress = [NSProgress progressWithTotalUnitCount:10];
    //對任務進度對象的完成比例進行監聽
    [progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:nil];
    //向下分支出一個子任務 子任務進度總數爲5個單元 即當子任務完成時 父progerss對象進度走5個單元
    [progress becomeCurrentWithPendingUnitCount:5];
    [self subTaskOne];
    [progress resignCurrent];
    //向下分出第2個子任務
    [progress becomeCurrentWithPendingUnitCount:5];
    [self subTaskOne];
    [progress resignCurrent];
}

-(void)subTaskOne{
    //子任務總共有10個單元
    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);
}

NSProgress的這種樹狀設計模式乍看起來確實有些使人費解,有一點須要注意,becomeCurrentWithPendingUnitCount:方法的意義是將此NSProgress對象註冊爲當前線程任務的根進度管理對象,resignCurrent方法爲取消註冊,這兩個方法必須成對出現,當一個NSProgress對象被註冊爲當前線程的根節點時,後面使用類方法 progressWithTotalUnitCount:建立的NSProgress對象都默認做爲子節點添加。spa

4、iOS9以後進行多任務進度監聽的新設計方法

        正如上面的例子所演示,註冊根節點的方式可讀性不好,代碼結構也不太清晰,可能Apple的工程師們也以爲如此,在iOS9以後,NSProgress類中又添加了一些方法,經過這些方法能夠更加清晰的表達進度指示器之間的層級結構,示例代碼以下:線程

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //這個方法將建立任務進度管理對象 UnitCount是一個基於UI上的完整任務的單元數
    progress = [NSProgress progressWithTotalUnitCount:10];
    //對任務進度對象的完成比例進行監聽
    [progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:nil];
    //建立子節點
    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 ++;
    }
}

如上面代碼所示,代碼結構變得更加清晰,可操做性也更強了。設計

5、一點小總結

//獲取當前線程的進度管理對象根節點
//注意:當有NSProgress對象調用了becomeCurrentWithPendingUnitCount:方法後,這個方法才能獲取到
+ (nullable NSProgress *)currentProgress;
//建立一個NSProgress對象,須要傳入進度的單元數量
+ (NSProgress *)progressWithTotalUnitCount:(int64_t)unitCount;
//和上一個方法功能類似 iOS9以後的新方法
+ (NSProgress *)discreteProgressWithTotalUnitCount:(int64_t)unitCount;
//iOS9以後的新方法 建立某個進度指示器節點的子節點
+ (NSProgress *)progressWithTotalUnitCount:(int64_t)unitCount parent:(NSProgress *)parent pendingUnitCount:(int64_t)portionOfParentTotalUnitCount;
//NSProgress實例的初始化方法 自父節點參數能夠爲nil
- (instancetype)initWithParent:(nullable NSProgress *)parentProgressOrNil userInfo:(nullable NSDictionary *)userInfoOrNil;
//註冊爲當前線程根節點
- (void)becomeCurrentWithPendingUnitCount:(int64_t)unitCount;
//取消註冊 與註冊方法必須同步出現
- (void)resignCurrent;
//iOS9新方法 向一個節點中添加一個子節點
- (void)addChild:(NSProgress *)child withPendingUnitCount:(int64_t)inUnitCount;
//進度單元總數
@property int64_t totalUnitCount;
//已完成的進度單元數
@property int64_t completedUnitCount;
//是否可取消
@property (getter=isCancellable) BOOL cancellable;
//是否可暫停
@property (getter=isPausable) BOOL pausable;
//進度比例 0-1之間
@property (readonly) double fractionCompleted;
//取消
- (void)cancel;
//暫停
- (void)pause;
//恢復
- (void)resume

6、關於NSProgress對象的用戶配置字典

        在NSProgress對象的用戶字典中能夠設置一些特定的鍵值來進行顯示模式的設置,示例以下:code

//設置剩餘時間 會影響localizedAdditionalDescription的值
/*
例如:0 of 10 — About 10 seconds remaining
*/
[progress setUserInfoObject:@10 forKey:NSProgressEstimatedTimeRemainingKey];
//設置完成速度信息 會影響localizedAdditionalDescription的值
/*
例如:Zero KB of 10 bytes (15 bytes/sec)
*/
[progress setUserInfoObject:@15 forKey:NSProgressThroughputKey];
/*
下面這些鍵值的生效 必須將NSProgress對象的kind屬性設置爲 NSProgressKindFile
NSProgressFileOperationKindKey鍵對應的是提示文字類型 會影響localizedDescription的值
NSProgressFileOperationKindKey可選的對應值以下:
NSProgressFileOperationKindDownloading: 顯示Downloading files…
NSProgressFileOperationKindDecompressingAfterDownloading: 顯示Decompressing files…
NSProgressFileOperationKindReceiving: 顯示Receiving files…
NSProgressFileOperationKindCopying: 顯示Copying files…
*/
 [progress setUserInfoObject:NSProgressFileOperationKindDownloading forKey:NSProgressFileOperationKindKey];
/*
NSProgressFileTotalCountKey鍵設置顯示的文件總數 
例如:Copying 100 files…
*/
 [progress setUserInfoObject:@100 forKey:NSProgressFileTotalCountKey];
//設置已完成的數量
[progress setUserInfoObject:@1 forKey:NSProgressFileCompletedCountKey];

專一技術,熱愛生活,交流技術,也作朋友。server

——琿少 QQ羣:203317592對象

相關文章
相關標籤/搜索