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

  • 相关阅读:
    null in ABAP and nullpointer in Java
    SAP ABAP SM50事务码和Hybris Commerce的线程管理器
    Hybris service layer和SAP CRM WebClient UI架构的横向比较
    SAP ABAP和Linux系统里如何检查网络传输的数据量
    SAP CRM WebClient UI和Hybris的controller是如何被调用的
    SAP CRM和Cloud for Customer订单中的业务伙伴的自动决定机制
    SAP CRM WebClient UI和Hybris CommerceUI tag的渲染逻辑
    SAP BSP和JSP页面里UI元素的ID生成逻辑
    微信jsapi支付
    微信jsapi退款操作
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3622582.html
Copyright © 2011-2022 走看看