zoukankan      html  css  js  c++  java
  • 使用开源库 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

  • 相关阅读:
    asp.net字符串分割函数用法
    Nginx启动/重启脚本详解
    jQuery获取对象简单实现方法
    python字符串格式化之学习笔记
    asp.net中Winform开发框架之数据即时更新的实现
    Nginx错误提示:504 Gateway Time-out解决方法
    实用的php购物车程序
    sql datalength与len区别用法
    异步加载js文件的方法总结
    面向对象泛型问题
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3622582.html
Copyright © 2011-2022 走看看