MBProgressHUD的备忘录模式:保存指示器的历史状态

MBProgressHUD的备忘录模式:保存指示器的历史状态

【免费下载链接】MBProgressHUD MBProgressHUD + Customizations 【免费下载链接】MBProgressHUD 项目地址: https://gitcode.com/gh_mirrors/mb/MBProgressHUD

在移动应用开发中,用户经常需要在执行耗时操作时看到清晰的进度反馈。然而,当应用需要显示多个连续任务的进度时,频繁创建和销毁指示器不仅繁琐,还可能导致界面闪烁和状态丢失。本文将介绍如何使用备忘录模式(Memento Pattern)为MBProgressHUD实现状态保存功能,让你轻松管理多个进度指示器的显示与切换。

为什么需要状态保存?

想象以下场景:用户在文件上传过程中需要同时下载数据,两个操作都需要显示进度指示器。如果直接切换指示器的属性(如模式、进度值、文本),不仅代码逻辑混乱,还可能丢失前一个任务的状态信息。备忘录模式通过捕获对象内部状态并在外部存储,完美解决了这一问题。

MBProgressHUD作为iOS开发中最常用的指示器库,其核心类MBProgressHUD.h提供了丰富的可配置属性,但原生并不支持状态保存功能。我们将通过扩展该类实现备忘录模式,主要涉及以下步骤:

mermaid

实现备忘录模式

1. 定义备忘录类

首先创建一个存储HUD状态的类MBProgressHUDMemento,用于保存关键属性:

@interface MBProgressHUDMemento : NSObject
@property (nonatomic, assign) MBProgressHUDMode mode;
@property (nonatomic, assign) float progress;
@property (nonatomic, copy) NSString *labelText;
@property (nonatomic, copy) NSString *detailsLabelText;
@property (nonatomic, strong) UIView *customView;
@end

@implementation MBProgressHUDMemento
// 实现自动生成的getter/setter
@end

2. 扩展MBProgressHUD

MBProgressHUD.h中添加备忘录相关方法声明:

@interface MBProgressHUD (Memento)
- (MBProgressHUDMemento *)saveState;
- (void)restoreState:(MBProgressHUDMemento *)memento;
@end

MBProgressHUD.m中实现这些方法:

@implementation MBProgressHUD (Memento)

- (MBProgressHUDMemento *)saveState {
    MBProgressHUDMemento *memento = [[MBProgressHUDMemento alloc] init];
    memento.mode = self.mode;
    memento.progress = self.progress;
    memento.labelText = self.label.text;
    memento.detailsLabelText = self.detailsLabel.text;
    memento.customView = self.customView;
    return memento;
}

- (void)restoreState:(MBProgressHUDMemento *)memento {
    self.mode = memento.mode;
    self.progress = memento.progress;
    self.label.text = memento.labelText;
    self.detailsLabel.text = memento.detailsLabelText;
    self.customView = memento.customView;
    [self updateIndicators]; // 关键:更新UI显示
}

@end

注意updateIndicators方法来自MBProgressHUD.m,用于根据当前属性重新布局UI组件。

3. 管理多个状态

创建状态管理类MBProgressHUDStateManager,使用栈结构存储多个备忘录:

@interface MBProgressHUDStateManager : NSObject
- (void)pushStateForHUD:(MBProgressHUD *)hud;
- (void)popStateForHUD:(MBProgressHUD *)hud;
@end

@implementation MBProgressHUDStateManager {
    NSMutableDictionary<MBProgressHUD *, NSMutableArray<MBProgressHUDMemento *> *> *_stateStacks;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _stateStacks = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)pushStateForHUD:(MBProgressHUD *)hud {
    if (!_stateStacks[hud]) {
        _stateStacks[hud] = [NSMutableArray array];
    }
    [_stateStacks[hud] addObject:[hud saveState]];
}

- (void)popStateForHUD:(MBProgressHUD *)hud {
    NSMutableArray *stack = _stateStacks[hud];
    if (stack.count == 0) return;
    
    MBProgressHUDMemento *memento = [stack lastObject];
    [stack removeLastObject];
    [hud restoreState:memento];
    
    if (stack.count == 0) {
        [_stateStacks removeObjectForKey:hud];
    }
}

@end

实际应用场景

文件上传下载示例

以下代码演示如何在文件上传和下载任务间切换HUD状态:

// 创建HUD
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeDeterminate;
hud.label.text = @"上传中";

// 创建状态管理器
MBProgressHUDStateManager *manager = [[MBProgressHUDStateManager alloc] init];

// 保存上传状态
[manager pushStateForHUD:hud];

// 切换到下载状态
hud.mode = MBProgressHUDModeAnnularDeterminate;
hud.label.text = @"下载中";
hud.progress = 0.3;

// 恢复上传状态
[manager popStateForHUD:hud];
// 此时HUD将恢复为上传模式,进度值和文本也会回到之前的状态

自定义视图切换

利用备忘录模式保存包含自定义视图的状态:

// 创建带对勾图标的完成状态
UIImageView *checkmarkView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Checkmark"]];
hud.mode = MBProgressHUDModeCustomView;
hud.customView = checkmarkView;
hud.label.text = @"完成";

// 保存完成状态
[manager pushStateForHUD:hud];

// 切换到加载状态
hud.mode = MBProgressHUDModeIndeterminate;
hud.label.text = @"加载中";

// 恢复完成状态
[manager popStateForHUD:hud];

项目中提供了示例图标Checkmark.png,可直接用于自定义视图。

高级扩展

1. 持久化存储

通过归档将备忘录保存到本地,实现应用重启后恢复HUD状态:

// 归档
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:memento requiringSecureCoding:NO error:nil];
[data writeToFile:path atomically:YES];

// 解档
NSData *data = [NSData dataWithContentsOfFile:path];
MBProgressHUDMemento *memento = [NSKeyedUnarchiver unarchiveObjectOfClass:[MBProgressHUDMemento class] fromData:data error:nil];

2. 动画过渡效果

restoreState:方法中添加过渡动画:

- (void)restoreState:(MBProgressHUDMemento *)memento animated:(BOOL)animated {
    if (animated) {
        [UIView animateWithDuration:0.3 animations:^{
            self.bezelView.alpha = 0;
        } completion:^(BOOL finished) {
            [self restoreState:memento];
            [UIView animateWithDuration:0.3 animations:^{
                self.bezelView.alpha = 1;
            }];
        }];
    } else {
        [self restoreState:memento];
    }
}

动画实现参考了MBProgressHUD.m中的animateIn:withType:completion:方法。

3. 与NSProgress集成

利用MBProgressHUD的progressObject属性(定义在MBProgressHUD.h),可以将备忘录与系统进度对象结合:

// 在备忘录中添加NSProgress引用
@property (nonatomic, strong) NSProgress *progressObject;

// 保存/恢复进度对象
memento.progressObject = self.progressObject;
self.progressObject = memento.progressObject;

总结

通过备忘录模式,我们为MBProgressHUD添加了状态保存与恢复功能,主要解决了以下问题:

  1. 状态丢失:避免直接修改HUD属性导致的状态混乱
  2. 代码复杂度:将状态管理逻辑与UI逻辑分离
  3. 用户体验:实现任务切换时的平滑过渡

完整代码可参考项目Demo目录中的示例HudDemoViewController.m,该文件包含了多种HUD样式的使用示例,可作为扩展功能的基础。

使用此模式时需注意:

  • 避免保存过大的自定义视图,以免影响性能
  • 状态栈深度不宜过大,建议不超过5层
  • 确保在主线程调用状态恢复方法,避免UI异常

通过这种设计,我们不仅增强了MBProgressHUD的功能,还保持了原库的简洁API设计风格,让复杂的状态管理变得简单直观。

【免费下载链接】MBProgressHUD MBProgressHUD + Customizations 【免费下载链接】MBProgressHUD 项目地址: https://gitcode.com/gh_mirrors/mb/MBProgressHUD

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值