由于多个业务需要,在一个界面会有多个弹框的存在,而这多个弹框需要按顺序、优先级给统一管理起来,不然会杂乱无章的弹出,用户会一脸懵逼啊。
我写了一个管理器,把弹框的出现和消失给管理起来,出现和消失的时机给管理起来。
AlertManager
不关心怎么显示和消失,也就是不关系的UI层面,只管理显示和消失两个block事件。
实现的功能:
- 统一管理弹框
- 弹框叠加显现
- 弹框依次显现
- 弹框的优先级排序
- 弹框被拦截缓存起来;允许激活会在别的弹框消失后显示
头文件
@interface AlertManager : NSObject
+ (instancetype)shareManager;
/// 是否根据优先级排序 默认YES
@property (nonatomic,assign,readonly) BOOL isSortByPriority;
///被遮挡后的弹框先隐藏 默认是YES显示
@property (nonatomic,assign,readonly) BOOL isDisplayAfterCover;
/// 弹框展示
/// @param config 配置
/// @param showBlock 显示回调
/// @param dismissBlock 隐藏回调
- (void)alertShowWithConfig:(AlertConfig *)config show:(Block)showBlock dismiss:(Block)dismissBlock;
/// 清除弹框
- (void)alertDissMiss;
/// 清楚缓存
- (void)clearCache;
@end
管理器添加弹框代码
- (void)alertShowWithConfig:(AlertConfig *)config
show:(nonnull Block)showBlock
dismiss:(nonnull Block)dismissBlock{
NSString *type = [NSString stringWithFormat:@"type%ld",(long)self.num];//累加的type
self.num++;
//排查是否重复添加
NSArray * keys = self.alertCache.allKeys;
if ([keys containsObject:type]) {
showBlock(NO,@"type标识重复");
return;
}
//重置优先级
if (config.priority != AlertPriority1 && config.priority != AlertPriority2 && config.priority != AlertPriority3) {
config.priority = AlertPriority1;
}
config.alertType = type;
config.showBlock = showBlock;
config.dismissBlock = dismissBlock;
config.isDisplay = YES;//设置为当前显示
//加入缓存
ZJSemaphoreCreate
ZJSemaphoreWait
[self.alertCache setObject:config forKey:type];
ZJSemaphoreSignal
if (config.isIntercept && self.alertCache.allKeys.count > 1) {//self.alertCache.allKeys.count > 1 表示当前有弹框在显示
//在此移除被拦截并且不被激活的弹框
if (!config.isActivate) {
ZJSemaphoreCreate
ZJSemaphoreWait
[self.alertCache removeObjectForKey:type];
ZJSemaphoreSignal
}
config.isDisplay = NO;//重置为当前隐藏
return;
}
//隐藏已经显示的弹框
if (!self.isDisplayAfterCover) {
NSArray * allKeys = [self.alertCache allKeys];
for (NSString *key in allKeys) {
AlertConfig *alertConfig = [self.alertCache objectForKey:key];
if (alertConfig.isDisplay&&alertConfig.dismissBlock&&alertConfig!=config) {
alertConfig.isDisplay = NO;
alertConfig.dismissBlock(YES,@"本次被隐藏了啊");
}
}
}
ZJSemaphoreCreate1
ZJSemaphoreWait1
[self.currentDisplayAlerts addObject:config];
ZJSemaphoreSignal1
showBlock(YES,@"");
}
弹框消失的代码
- (void)alertDissMiss{
//查找当前最上边的弹框
AlertConfig *alertConfig = [self findAlertCurrentDisplay];
if (alertConfig) {
Block dismissBlock = alertConfig.dismissBlock;
dismissBlock(YES,@"");
//延迟释放其他block
ZJSemaphoreCreate
ZJSemaphoreWait
[self.alertCache removeObjectForKey:alertConfig.alertType];
ZJSemaphoreSignal
ZJSemaphoreCreate1
ZJSemaphoreWait1
[self.currentDisplayAlerts removeLastObject];
ZJSemaphoreSignal1
}
NSArray * values = self.alertCache.allValues;
//判断当前是否有显示-有,不显示弹框拦截的弹框
if ([self displayAlert]) {
return;
}
if (self.isSortByPriority) {
values = [self sortByPriority:values];
}
//接下来是要显示被拦截的弹框
if (values.count > 0) {
//查找是否有可以显示的弹框 条件:1.已加入缓存 2.被拦截 3.可以激活显示
//目前是从先加入的找起->优先级
for (AlertConfig * config in values) {
Block showBlock = config.showBlock;
if (config.isIntercept && config.isActivate && showBlock) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.35 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
config.isDisplay = YES;
ZJSemaphoreCreate1
ZJSemaphoreWait1
[self.currentDisplayAlerts addObject:config];
ZJSemaphoreSignal1
showBlock(YES,@"");
});
break;
}
}
}
}
具体使用
- (void)showAlertViewB {
AlertConfig * config = [[AlertConfig alloc]initWithPatams:@{} activate:YES];
config.priority = AlertPriority3;
__weak typeof(self) weakSelf = self;
[self.manager alertShowWithConfig:config show:^(BOOL isSuccess, NSString * _Nonnull message) {
if (isSuccess) {
__strong typeof(weakSelf) strongSelf = weakSelf;
strongSelf.alertViewB.hidden = NO;
}
} dismiss:^(BOOL isSuccess, NSString * _Nonnull message) {
__strong typeof(weakSelf) strongSelf = weakSelf;
strongSelf.alertViewB.hidden = YES;
}];
}
- (void)hiddenAlertViewB {
[self.manager alertDissMiss];
}
既然是弹框的统一管理,将要显示的弹框一定要加载管理器内来显示和移除才能起到作用。让管理器来管理弹框的显示和消失。
代码地址:https://github.com/zhengju/iOSDemos/tree/master/SpringBox