MBProgressHUD源码学习1:公有API介绍

  • 源代码基于0.91版本;
  • 本篇只介绍相关公有API,同时简单说明实现方式

1. 用于快速调用HUD的类方法

1.1 在指定视图上显示和移除HUD

  • 在视图中显示HUD,进入等待状态
+ (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated;
  • 在视图上移除HUD,退出等待状态
+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated;

对于没有特别要求,只需要简单屏蔽用户交互时使用;二者一般成对使用。

  • 移除视图中的所有HUD,退出等待状态
+ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated;

此方法会遍历查找视图层级中的所有HUD视图并移除。

快速显示和隐藏HUD方法,自动管理HUD的生命周期,故在实现中设置为“隐藏后直接移除视图”,如:

// 示例的显示HUD方法
+ (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated {
    MBProgressHUD *hud = [[self alloc] initWithView:view];
    // 类方法,只是用于快速显示或隐藏,不关心视图,故消失后直接移除
    hud.removeFromSuperViewOnHide = YES;
    [view addSubview:hud];
    [hud show:animated];
    return MB_AUTORELEASE(hud);
}

1.2 获取视图中存在的HUD对象

  • 获取视图中当前显示的HUD对象
+ (MB_INSTANCETYPE)HUDForView:(UIView *)view;

这里使用了逆序遍历view的子视图的方式,快速获取最上层的HUD对象:

+ (MB_INSTANCETYPE)HUDForView:(UIView *)view {
    // 逆序迭代(符合视图层级)
    NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator];
    for (UIView *subview in subviewsEnum) {
        if ([subview isKindOfClass:self]) {
            return (MBProgressHUD *)subview;
        }
    }
    return nil;
}
  • 获取视图中所有存在的HUD对象
+ (NSArray *)allHUDsForView:(UIView *)view;

2 初始化HUD的实例方法

2.1 使用UIWindow对象尺寸创建HUD

- (id)initWithWindow:(UIWindow *)window;

2.2 使用UIView对象尺寸创建HUD

- (id)initWithView:(UIView *)view;

说明:

  • 二者都是通过调用initWithFrame方法进行实例化,只是参数类型不同;
  • 需要创建方自主管理HUD的生存周期。

注意:

  • 以上初始化方法中的参数只是由于指定HUD视图自身尺寸,并非添加到视图上。
  • 添加到的父视图需要手动指定。

3 显示、隐藏HUD的相关实例方法

3.1 显示HUD视图,进入等待状态

- (void)show:(BOOL)animated;

3.2 隐藏HUD视图,退出等待状态

- (void)hide:(BOOL)animated;

3.3 在指定时间后,隐藏HUD视图,退出等待状态

- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay;

以上方法,都是在通过自己实例化HUD对象后(默认为隐藏状态),自主控制HUD视图的显示与隐藏。

4 在指定任务执行时,自动显示和隐藏HUD的相关方法

4.1 使用“target - selector”方式执行后台任务

- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated;

此方法的实现步骤:

  1. 在后台自动创建新线程,在其中执行预定任务;
  2. 同时在主线程创建并显示HUD;
  3. 任务完成后,在主线程中清理缓存数据,同时移除HUD,结束等待状态。
- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated {
    // 保存需要执行的参数对象
    methodForExecution = method;
    targetForExecution = MB_RETAIN(target);
    objectForExecution = MB_RETAIN(object); 
    // 这里由于是开辟新线程执行任务,故是异步执行
    self.taskInProgress = YES;
    [NSThread detachNewThreadSelector:@selector(launchExecution) toTarget:self withObject:nil];
    // 同时显示HUD视图,进入等待状态
    [self show:animated];
}

- (void)launchExecution {
    @autoreleasepool {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        // 1.这里由于没有使用返回值,故需要向编译器添加“忽略内存泄漏”要求
        // 2.此方法在支持完毕前,不会返回(卡住当前执行线程)
        [targetForExecution performSelector:methodForExecution withObject:objectForExecution];
#pragma clang diagnostic pop
        // 执行完毕后,执行主线程的任务
        [self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO];
    }
}

- (void)cleanUp {
    // 标识任务已结束
    taskInProgress = NO;
#if !__has_feature(objc_arc)
    [targetForExecution release];
    [objectForExecution release];
#else
    // 清除保留的执行对象
    targetForExecution = nil;
    objectForExecution = nil;
#endif
    // 隐藏HUD视图,退出等待状态
    [self hide:useAnimation];
}

4.2 使用“block”方式执行后台任务

- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block;

4.3 使用“block”方式执行后台任务,并在完成后执行指定任务

- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(MBProgressHUDCompletionBlock)completion;

4.4 使用“block”方式执行后台任务,任务在指定的GCD队列中执行

- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue;

4.5 使用“block”方式执行后台任务,任务在指定的GCD队列中执行,并在完成后执行指定任务

- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue
          completionBlock:(MBProgressHUDCompletionBlock)completion;

以上通过block方式执行任务的API,都是通过GCD的方式,在并发队列中执行异步任务,简化了实现。如1.4.5的方法实现:

/** 真正的block版本的异步执行函数 */
- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue
     completionBlock:(MBProgressHUDCompletionBlock)completion {
    // 标识任务已开始执行
    self.taskInProgress = YES;
    // 将block保存到堆内存(由于completion为外部回调,不会捕获当前对象中的变量,防止是栈内存的block被释放,故需要拷贝到堆上)
    self.completionBlock = completion;
    // 在队列中异步执行任务
    dispatch_async(queue, ^(void) {
        block();
        // 完成后,主线程进行清理工作
        dispatch_async(dispatch_get_main_queue(), ^(void) {
            [self cleanUp];
        });
    });
    // 同时,在主线程显示HUD视图,进入等待状态
    [self show:animated];
}

你可能感兴趣的:(MBProgressHUD源码学习1:公有API介绍)