source https://github.com/jdg/MBProgressHUD
MBProgressHUD is an iOS drop-in class that displays a translucent HUD with an indicator and/or labels while work is being done in a background thread. The HUD is meant as a replacement for the undocumented, private UIKit UIProgressHUD with some additional features.
MBProgressHUD是一个iOS中继承的子类,当在后台线程中执行一些任务时,将展示出一个半透明的指示器或者标签.毫无疑问,HUD是用来替换苹果自身使用的私有API的,但同时该HUD会提供更多地特性.
以下是本人使用该开源库的心得分享以及简单地使用教程
1. 将MBProgressHUD.h MBProgressHUD.m 拖入到工程项目当中,MBProgressHUD本身支持ARC与非ARC
看其源码,其控制ARC与非ARC的宏值得学习
#if __has_feature(objc_instancetype)
#define MB_INSTANCETYPE instancetype
#else
#define MB_INSTANCETYPE id
#endif
#if __has_feature(objc_arc)
#define MB_STRONG strong
#else
#define MB_STRONG retain
#endif
#if __has_feature(objc_arc_weak)
#define MB_WEAK weak
#elif __has_feature(objc_arc)
#define MB_WEAK unsafe_unretained
#else
#define MB_WEAK assign
#endif
#if __has_feature(objc_arc)
#define MB_AUTORELEASE(exp) exp
#define MB_RELEASE(exp) exp
#define MB_RETAIN(exp) exp
#else
#define MB_AUTORELEASE(exp) [exp autorelease]
#define MB_RELEASE(exp) [exp release]
#define MB_RETAIN(exp) [exp retain]
#endif
2. 初始化以及简单地使用心得
我用同步网络请求来模拟阻塞操作,请将以下两个文件添加进工程项目中
YXSTHTTPRequest.h
#import <UIKit/UIKit.h> @interface YXSTHTTPRequest : NSObject /** 同步网络请求 这是用来进行同步网络请求的,该网络请求忽略本地缓存,使用此同步网络请求需要配合线程使用,否则会阻塞主线程 @param url 网络地址字符串 @param timeOut 超时的时间(当把请求设置成POST时,请求时间会被设置成240秒的默认值,自己设置的低于240秒的无效) @param setRequest 一个用于配置 NSMutableURLRequest 的 block @param result 当同步请求有效时,接收数据,或者出错时接收error block @return none */ + (void)syncConnectionWithURL:(NSString *)url timeOut:(NSTimeInterval)time setRequest:(void (^)(NSMutableURLRequest *request))setRequest result:(void (^)(NSData *data, NSError *error))result; @end
YXSTHTTPRequest.m
#import "YXSTHTTPRequest.h" @implementation RootViewController + (void)syncConnectionWithURL:(NSString *)url timeOut:(NSTimeInterval)time setRequest:(void (^)(NSMutableURLRequest *request))setRequest result:(void (^)(NSData *data, NSError *error))result { //创建一个网络请求 //NSURLRequestReloadIgnoringLocalCacheData(忽略本地缓存) NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:time]; //配置request setRequest(request); //开始同步链接 //The downloaded data for the URL request. Returns nil if a connection could not be created or if the download fails. NSError *connectionError = nil; NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&connectionError]; result(data, connectionError); } @end
几个关于线程的宏定义
// 系统子线程池(并发执行) #define SYS_CONCURRENT_QUEUE_H dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) #define SYS_CONCURRENT_QUEUE_D dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) #define SYS_CONCURRENT_QUEUE_L dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0) #define SYS_CONCURRENT_QUEUE_B dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) // 系统主线程池(序列执行) #define SYS_SERIAL_QUEUE dispatch_get_main_queue() #define SYS_UI_QUEUE dispatch_get_main_queue()
初始化以及使用的步骤
// 初始化 MBProgressHUD 对象 MBProgressHUD *hud = [[MBProgressHUD alloc] initWithWindow:self.view.window]; // 添加进当前视图中 [self.view addSubview:hud]; // 显示动画 [hud showAnimated:YES whileExecutingBlock:^{ // 阻塞的代码 // 请在此处添加需要等待操作的代码 } onQueue:SYS_SERIAL_QUEUE completionBlock:^{ // 结束后从父视图中移除 [hud removeFromSuperview]; [hud release]; }];
查看其源码(如下所示),其whileExecutingBlock执行在queue中,也就是说需要自己给queue设定参数,要么是序列化queue,要么是并发queue,注意
- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue completionBlock:(MBProgressHUDCompletionBlock)completion { self.taskInProgress = YES; self.completionBlock = completion; dispatch_async(queue, ^(void) { block(); dispatch_async(dispatch_get_main_queue(), ^(void) { [self cleanUp]; }); }); [self show:animated]; }
一般情况下,我们需要使用序列queue(dispatch_get_main_queue()),以下是一个完整地使用示例(请将代码放入一个button事件中)
// 初始化 MBProgressHUD 对象 MBProgressHUD *hud = [[MBProgressHUD alloc] initWithWindow:self.view.window]; // 添加进当前视图中 [self.view addSubview:hud]; // 显示动画 [hud showAnimated:YES whileExecutingBlock:^{ // 阻塞操作 NSString *urlStr = @"http://wallpapers.wallbase.cc/rozne/wallpaper-2903212.jpg"; [YXSTHTTPRequest syncConnectionWithURL:urlStr timeOut:20 setRequest:^(NSMutableURLRequest *request) { } result:^(NSData *data, NSError *error) { if (error == nil) { NSLog(@"完成"); } }]; } onQueue:SYS_SERIAL_QUEUE completionBlock:^{ // 结束后从父视图中移除 [hud removeFromSuperview]; [hud release]; }];
显示下载进度条(无法使用block的方式,需要设置代理)
// 初始化 MBProgressHUD 对象 hud = [[MBProgressHUD alloc] initWithWindow:self.view.window]; // 添加进父视图 [self.view addSubview:hud]; // 下载进度模式 hud.mode = MBProgressHUDModeDeterminate; // 标签 hud.labelText = @"正在下载"; // 协议 hud.delegate = self; // 执行 [hud showWhileExecuting:@selector(myProgress) onTarget:self withObject:nil animated:YES]; - (void)myProgress { // 进度条显示 float progress = 0.0f; while (progress < 1.0f) { progress += 0.01f; hud.progress = progress; usleep(50000); } } - (void)hudWasHidden:(MBProgressHUD *)hud { // Remove HUD from screen when the HUD was hidded [hud removeFromSuperview]; [hud release]; hud = nil; }
以下3个枚举值反应了3中下载进度的图形显示,均属于下载进度模式
MBProgressHUDModeDeterminate
MBProgressHUDModeDeterminateHorizontalBar
MBProgressHUDModeAnnularDeterminate
接下来是比较复杂的混合模式,混合了几个阶段,非常实用
@interface RootViewController ()<MBProgressHUDDelegate> { MBProgressHUD *HUD; } @end - (void)buttonsEvent:(UIButton *)button { HUD = [[MBProgressHUD alloc] initWithView:self.view]; [self.view addSubview:HUD]; HUD.delegate = self; HUD.labelText = @"连接网络..."; HUD.minSize = CGSizeMake(135.f, 135.f); [HUD showWhileExecuting:@selector(myMixedTask) onTarget:self withObject:nil animated:YES]; } - (void)myMixedTask { // 阻塞操作(请将阻塞操作代替sleep函数) sleep(2); // 切换到下载模式(请将阻塞操作代替usleep函数) HUD.mode = MBProgressHUDModeDeterminate; HUD.labelText = @"下载进度"; float progress = 0.0f; while (progress < 1.0f) { progress += 0.01f; HUD.progress = progress; usleep(50000); } // 切换到默认显示的模式(请将阻塞操作代替sleep函数) HUD.mode = MBProgressHUDModeIndeterminate; HUD.labelText = @"清理完毕"; sleep(2); // 切换到自定义图片的模式,在主线程中显示图片(说明此方法执行在子线程中) __block UIImageView *imageView; dispatch_sync(SYS_UI_QUEUE, ^{ UIImage *image = [UIImage imageNamed:@"37x-Checkmark.png"]; imageView = [[UIImageView alloc] initWithImage:image]; }); HUD.customView = [imageView autorelease]; HUD.mode = MBProgressHUDModeCustomView; HUD.labelText = @"完成"; // 延时2秒后消失 sleep(2); } - (void)hudWasHidden:(MBProgressHUD *)hud { // Remove HUD from screen when the HUD was hidded [hud removeFromSuperview]; [hud release]; hud = nil; }
总结:
1. 涉及到下载进度的时候,必须使用代理来实现进度条的显示
2. 这是用来指示阻塞操作的指示器
3. 混合模式使用非常方便
4. 可以使用自定义View