MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Objective-C中的MBProgressHUD加载提示框使用

2021-01-235.0k 阅读

一、MBProgressHUD简介

MBProgressHUD 是一个在 iOS 开发中广泛使用的轻量级 HUD(Heads-Up Display)框架,用于显示加载提示、状态信息等。它为开发者提供了一种简单且高效的方式来向用户反馈应用程序的当前状态,提升用户体验。在 Objective-C 项目中,MBProgressHUD 同样发挥着重要作用。

MBProgressHUD 具有以下特点:

  1. 高度可定制:可以根据项目需求自定义 HUD 的样式,包括颜色、透明度、动画效果等。
  2. 简单易用:其 API 设计简洁明了,即使是初学者也能快速上手并集成到项目中。
  3. 多种展示方式:支持多种提示类型,如纯加载指示器、带有文字提示的加载指示器、成功/失败提示等。

二、MBProgressHUD的安装与配置

  1. 安装方式
    • CocoaPods:在项目的 Podfile 文件中添加 pod 'MBProgressHUD',然后执行 pod install 命令。CocoaPods 会自动下载并集成 MBProgressHUD 到项目中。
    • 手动安装:从 GitHub 上下载 MBProgressHUD 的源代码,将 MBProgressHUD.hMBProgressHUD.m 文件拖入项目中。同时,还需要导入 QuartzCore.framework,因为 MBProgressHUD 使用了一些 Core Animation 相关的功能。
  2. 配置项目
    • 导入头文件:在需要使用 MBProgressHUD 的文件中,导入 #import "MBProgressHUD.h"
    • 设置外观(可选):可以全局设置 MBProgressHUD 的外观属性,例如:
// 设置 HUD 的背景颜色
[MBProgressHUD appearance].backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
// 设置 HUD 的前景颜色
[MBProgressHUD appearance].foregroundColor = [UIColor whiteColor];

这样设置后,所有的 MBProgressHUD 实例都会使用这些外观属性,除非在实例化时单独进行覆盖。

三、MBProgressHUD的基本使用

  1. 显示加载指示器
    • 简单显示:在视图控制器中显示一个简单的加载指示器,代码如下:
- (void)showLoadingHUD {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeIndeterminate;
    hud.label.text = @"加载中...";
}

在上述代码中,首先通过 [MBProgressHUD showHUDAddedTo:self.view animated:YES] 创建并显示一个 HUD 到当前视图控制器的视图上。animated:YES 表示以动画方式显示。然后设置 hud.modeMBProgressHUDModeIndeterminate,这是一种不确定进度的模式,通常显示为旋转的指示器。最后设置 hud.label.text 为加载提示文字。 - 指定位置显示:有时需要将加载指示器显示在特定位置,例如屏幕中心,可以这样实现:

- (void)showLoadingHUDAtCenter {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeIndeterminate;
    hud.label.text = @"加载中...";
    hud.center = self.view.center;
}

通过设置 hud.center 为视图的中心,加载指示器就会显示在屏幕中心位置。 2. 显示带有进度的加载指示器 当有明确的进度信息时,可以使用 MBProgressHUDModeDeterminate 模式来显示进度。例如,在进行文件下载时,可以这样更新进度:

- (void)showProgressHUD {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeDeterminate;
    hud.label.text = @"下载中...";
    // 模拟下载进度更新
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        for (int i = 0; i <= 100; i++) {
            dispatch_async(dispatch_get_main_queue(), ^{
                hud.progress = i / 100.0;
                if (i == 100) {
                    [hud hideAnimated:YES];
                }
            });
            sleep(1);
        }
    });
}

在这个例子中,首先创建一个模式为 MBProgressHUDModeDeterminate 的 HUD。然后在后台队列中模拟下载进度,通过 dispatch_async 将进度更新操作发送到主线程,因为 UI 更新必须在主线程进行。每次更新 hud.progress 的值,当进度达到 100% 时,隐藏 HUD。 3. 显示成功/失败提示 - 显示成功提示:当某个操作成功完成时,显示一个成功提示:

- (void)showSuccessHUD {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeText;
    hud.label.text = @"操作成功";
    hud.detailsLabel.text = @"详细信息:数据已保存";
    hud.offset = CGPointMake(0, -100);
    [hud hideAnimated:YES afterDelay:2];
}

这里设置 hud.modeMBProgressHUDModeText,只显示文字信息。通过 hud.label.text 设置主要提示文字,hud.detailsLabel.text 设置详细信息。hud.offset 可以调整 HUD 在视图中的位置,[hud hideAnimated:YES afterDelay:2] 表示在 2 秒后自动隐藏 HUD。 - 显示失败提示:类似地,当操作失败时显示失败提示:

- (void)showFailureHUD {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeText;
    hud.label.text = @"操作失败";
    hud.detailsLabel.text = @"详细信息:网络连接失败";
    hud.offset = CGPointMake(0, -100);
    [hud hideAnimated:YES afterDelay:2];
}

与成功提示类似,只是文字内容不同。

四、MBProgressHUD的高级定制

  1. 自定义 HUD 样式
    • 自定义背景样式:可以通过设置 hud.bezelView 的属性来自定义 HUD 的背景外观。例如,将背景设置为圆角矩形并带有阴影:
- (void)customizeHUDBackground {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.bezelView.backgroundColor = [UIColor whiteColor];
    hud.bezelView.layer.cornerRadius = 10;
    hud.bezelView.layer.shadowColor = [UIColor blackColor].CGColor;
    hud.bezelView.layer.shadowOffset = CGSizeMake(0, 2);
    hud.bezelView.layer.shadowOpacity = 0.5;
    hud.bezelView.layer.shadowRadius = 3;
}

在这段代码中,首先设置 hud.bezelView.backgroundColor 为白色,然后通过 layer 属性设置圆角半径、阴影颜色、偏移量、不透明度和半径,使 HUD 的背景看起来更加美观。 - 自定义指示器样式:对于 MBProgressHUDModeIndeterminate 模式的指示器,可以自定义其颜色和动画效果。例如,将指示器颜色改为蓝色,并使用自定义的旋转动画:

- (void)customizeIndicator {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeIndeterminate;
    hud.color = [UIColor blueColor];
    CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ];
    rotationAnimation.duration = 1.0;
    rotationAnimation.cumulative = YES;
    rotationAnimation.repeatCount = HUGE_VALF;
    [hud.activityIndicatorView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

这里设置 hud.color 为蓝色,然后创建一个 CABasicAnimation 动画,使指示器围绕 Z 轴旋转,设置动画的持续时间、是否累积和重复次数,并将动画添加到 hud.activityIndicatorView.layer 上。 2. 添加自定义视图到 HUD 有时标准的 HUD 样式不能满足需求,需要添加自定义视图。例如,添加一个自定义的图标到 HUD 中:

- (void)addCustomViewToHUD {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"customIcon"]];
    hud.customView = imageView;
    hud.mode = MBProgressHUDModeCustomView;
    hud.label.text = @"自定义提示";
}

在上述代码中,首先创建一个 UIImageView 并设置其显示的图片。然后将这个 imageView 设置为 hud.customView,并将 hud.mode 设置为 MBProgressHUDModeCustomView,表示使用自定义视图模式。最后设置提示文字。 3. 处理 HUD 的交互 MBProgressHUD 支持与用户的交互,例如在显示 HUD 时允许用户点击取消操作。可以通过设置 hud.userInteractionEnabledYES,并添加手势识别器来实现:

- (void)handleHUDInteraction {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.userInteractionEnabled = YES;
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissHUD)];
    [hud addGestureRecognizer:tapGesture];
}

- (void)dismissHUD {
    MBProgressHUD *hud = [MBProgressHUD HUDForView:self.view];
    [hud hideAnimated:YES];
}

handleHUDInteraction 方法中,首先设置 hud.userInteractionEnabledYES,使 HUD 可以响应触摸事件。然后创建一个 UITapGestureRecognizer 手势识别器,并将其添加到 HUD 上。当用户点击 HUD 时,会调用 dismissHUD 方法,隐藏 HUD。

五、在不同场景下使用 MBProgressHUD

  1. 网络请求场景 在进行网络请求时,MBProgressHUD 是显示加载状态的理想选择。以使用 AFNetworking 进行网络请求为例:
- (void)networkRequestWithHUD {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeIndeterminate;
    hud.label.text = @"加载数据...";
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager GET:@"https://example.com/api/data" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [hud hideAnimated:YES];
        // 处理成功响应
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [hud hideAnimated:YES];
        // 处理失败响应,显示错误提示
        MBProgressHUD *errorHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
        errorHUD.mode = MBProgressHUDModeText;
        errorHUD.label.text = @"网络请求失败";
        errorHUD.detailsLabel.text = error.localizedDescription;
        [errorHUD hideAnimated:YES afterDelay:2];
    }];
}

在这个例子中,在发起网络请求前显示加载 HUD,请求成功或失败时隐藏 HUD。如果请求失败,还会显示一个包含错误信息的 HUD。 2. 数据处理场景 当进行复杂的数据处理操作,如文件解压、数据加密等,也可以使用 MBProgressHUD 向用户反馈处理状态。例如,模拟一个文件解压过程:

- (void)unzipFileWithHUD {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeDeterminate;
    hud.label.text = @"解压文件...";
    // 模拟解压进度
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        for (int i = 0; i <= 100; i++) {
            dispatch_async(dispatch_get_main_queue(), ^{
                hud.progress = i / 100.0;
                if (i == 100) {
                    [hud hideAnimated:YES];
                    // 解压完成,显示成功提示
                    MBProgressHUD *successHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
                    successHUD.mode = MBProgressHUDModeText;
                    successHUD.label.text = @"解压成功";
                    [successHUD hideAnimated:YES afterDelay:2];
                }
            });
            sleep(1);
        }
    });
}

这里通过模拟解压进度,在主线程中更新 HUD 的进度,解压完成后隐藏当前 HUD 并显示一个成功提示的 HUD。 3. 多视图控制器场景 在应用程序中有多个视图控制器时,需要注意正确管理 MBProgressHUD 的显示和隐藏。一种常见的做法是在基类视图控制器中封装 HUD 的显示和隐藏方法,然后在子类中调用。例如:

// BaseViewController.m
#import "BaseViewController.h"
#import "MBProgressHUD.h"

@interface BaseViewController ()

@property (nonatomic, strong) MBProgressHUD *hud;

@end

@implementation BaseViewController

- (void)showHUDWithMessage:(NSString *)message {
    self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    self.hud.mode = MBProgressHUDModeIndeterminate;
    self.hud.label.text = message;
}

- (void)hideHUD {
    [self.hud hideAnimated:YES];
    self.hud = nil;
}

@end

// SubViewController.m
#import "SubViewController.h"

@interface SubViewController ()

@end

@implementation SubViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 显示 HUD
    [self showHUDWithMessage:@"加载数据"];
    // 模拟数据加载
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self hideHUD];
    });
}

@end

BaseViewController 中定义了 showHUDWithMessage:hideHUD 方法,方便子类视图控制器调用。在 SubViewController 中,通过调用基类方法来显示和隐藏 HUD。

六、MBProgressHUD使用中的常见问题及解决方法

  1. HUD显示异常
    • 问题描述:HUD 显示位置不正确,或者显示不完整。
    • 解决方法:检查 HUD 添加的视图是否正确,确保视图的大小和布局设置合理。例如,如果是在自定义视图中添加 HUD,要保证自定义视图的 frame 是正确的。同时,注意 hud.offsethud.center 等属性的设置,避免因错误的偏移导致显示异常。另外,在视图控制器的 viewDidLayoutSubviews 方法中更新 HUD 的位置,以确保在视图布局发生变化时 HUD 能正确显示。
  2. HUD隐藏不及时
    • 问题描述:操作完成后,HUD 没有及时隐藏。
    • 解决方法:检查隐藏 HUD 的代码是否在正确的回调中执行。例如,在网络请求成功或失败的回调中,确保 [hud hideAnimated:YES] 代码被正确调用。如果是在后台任务中更新 HUD 状态,要保证将隐藏 HUD 的操作通过 dispatch_async 发送到主线程执行,因为 UI 更新必须在主线程进行。
  3. HUD样式未生效
    • 问题描述:设置了自定义的 HUD 样式,如背景颜色、指示器颜色等,但没有生效。
    • 解决方法:确认设置样式的代码是否在 HUD 显示之前执行。如果在 HUD 显示之后设置样式,可能不会生效。另外,检查样式设置的属性是否正确,例如 hud.bezelView.backgroundColor 用于设置背景颜色,hud.color 用于设置指示器颜色等。对于一些自定义动画,要确保动画添加到了正确的 layer 上,并且动画的设置参数符合预期。

通过以上对 MBProgressHUD 在 Objective-C 中的使用介绍,从基本使用到高级定制,再到不同场景下的应用以及常见问题解决,开发者可以全面掌握如何在项目中有效地使用 MBProgressHUD 来提升用户体验。无论是简单的加载提示,还是复杂的自定义样式和交互,MBProgressHUD 都提供了丰富的功能和灵活的实现方式,满足各种项目需求。在实际开发中,根据具体场景合理运用 MBProgressHUD,将为应用程序增色不少。