使用开源库 MBProgressHUD 等待指示器

简介:

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

目录
相关文章
|
API iOS开发 Perl
iOS UIButton倒计时、指示器、粒子效果
iOS UIButton倒计时、指示器、粒子效果
iOS UIButton倒计时、指示器、粒子效果
|
API iOS开发 Perl
iOS UISlider自定义渐变色滑杆
iOS UISlider自定义渐变色滑杆
iOS UISlider自定义渐变色滑杆
|
iOS开发
如何使用iOS手势UIGestureRecognizer
如何使用iOS手势UIGestureRecognizer
80 0
|
iOS开发
iOS流布局UICollectionView系列一——初识与简单使用UICollectionView(二)
iOS流布局UICollectionView系列一——初识与简单使用UICollectionView
338 0
|
iOS开发
iOS流布局UICollectionView系列一——初识与简单使用UICollectionView(一)
iOS流布局UICollectionView系列一——初识与简单使用UICollectionView
236 0
iOS流布局UICollectionView系列一——初识与简单使用UICollectionView(一)
|
缓存 iOS开发 程序员