文档章节

iOS进度指示器——NSProgress

珲少
 珲少
发布于 2016/05/22 16:21
字数 1509
阅读 1803
收藏 14

iOS进度指示器——NSProgress

一、引言

        在iOS7之前,系统一直没有提供一个完整的框架来描述任务进度相关的功能。这使得在开发中进行耗时任务进度的监听将什么麻烦,在iOS7之后,系统提供了NSProgress类来专门报告任务进度。

二、创建单任务进度监听器

        单任务进度的监听是NSProgress最简单的一种运用场景,我们来用定时器模拟一个耗时任务,示例代码如下:

@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;

三、创建多任务进度监听器

        上面演示了只有一个任务时的进度监听方法,实际上,在开发中,一个任务中往往又有许多子任务,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对象都默认作为子节点添加。

四、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 ++;
    }
}

如上面代码所示,代码结构变得更加清晰,可操作性也更强了。

五、一点小总结

//获取当前线程的进度管理对象根节点
//注意:当有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

六、关于NSProgress对象的用户配置字典

        在NSProgress对象的用户字典中可以设置一些特定的键值来进行显示模式的设置,示例如下:

//设置剩余时间 会影响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];

专注技术,热爱生活,交流技术,也做朋友。

——珲少 QQ群:203317592

© 著作权归作者所有

共有 人打赏支持
珲少

珲少

粉丝 857
博文 384
码字总数 452377
作品 0
上海
iOS工程师
私信 提问
加载中

评论(1)

pennymei
pennymei
OneAPM 能快速捕捉性能表现差的应用代码,发现错误并随时向你发送警报,这一切只需下载并安装 OneAPM iOS SDK,然后更新你的应用,快来官网注册吧~
iOS7中Objective-C和Foundation的新特性

转自kingzwt2009的专栏 注意事项(Ray):文章来自iOS 7 by Tutorials iOS 7Feast的一部分(略) Objective-C 是最重要的iOS和OSX apps的开发工具。你可以使用其他语言的第三方框架开发apps,...

mingxun
2014/05/08
0
0
【书坊赠书福利——第二期】《iOS 8开发指南》

本周是人邮IT书坊赠书的第二期,第一期参与度极高,微信君在此感谢你们的支持,第一期获奖赠书已全部寄出。 本周赠品 本周,微信君给大家推荐@人民邮电出版社-信息技术分社 刚刚上架的新书《...

生气的散人
2014/09/23
371
0
iOS7中Objective-C和Foundation的新特性(What’s New in Obj

说明 注意事项(Ray):文章来自iOS 7 by Tutorials iOS 7Feast的一部分(略) Objective-C 是最重要的iOS和OSX apps的开发工具。你可以使用其他语言的第三方框架开发apps,例如HTML&Javasc...

我心java
2014/04/20
0
0
开源高仿印象笔记的iOS应用——朝夕笔记(Oncenote)

这是一款类似于印象笔记Evernote的生活类iOS应用——朝夕笔记 Oncenote。我希望能为更多的iOS开发者提供帮助与服务。当然App中还有不少bug和可扩展的功能模块,也希望各位开发者为该项目贡献...

503434355
2015/11/23
3.1K
1
【React Native开发】React Native控件之RefreshControl组件详解(21)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangqq781931404/article/details/50672747 const React =require('react-native');const {AppRegistry,Scro......

江清清
2016/02/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

ubuntu16.04 LNMP搭建 php7.1

sudo apt-get update sudo apt-get install mysql-server mysql-client sudo apt-add-repository ppa:ondrej/php sudo apt-get update sudo apt-get install php7.1 php7.1-fpm php7.1-cgi p......

一千零一夜个为什么
14分钟前
0
0
阿里云高级技术专家带你全面了解云主机性能评测

钱超,花名西邪,阿里云高级技术专家,超12年老阿里,是云主机性能领域的知名专家。 在目前的云计算测评领域,很多性能测评存在营销的包装,容易引起误导:比如用瞬时性能引导读者得出结论,...

阿里云官方博客
21分钟前
1
0
Charles如何设置本地映射、和取消本地映射

适用情况: 遇到接口返回特别快的时候非常郁闷,还得求着接口开发改数据很浪费时间,于是在这种情况下可以使用charles做本地映射。 环境: charles版本:3.11.2 一:如何设置本地映射 1、选中...

SuShine
23分钟前
1
0
python爬虫之定位网页元素的三种方式

python爬虫之定位网页元素的三种方式 2018年08月02日 13:30:02 Barry__ 阅读数:1373 标签: python 更多 个人分类: python 版权声明:本文为博主原创文章,转载请注明出处 https://blog.c...

linjin200
28分钟前
1
0
AES加密算法的详细介绍与实现

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "aes.h"/** * S盒 */static const int S[16][16] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc......

青春无极限
28分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部