iOS弹框统一管理器

作者: iOS俱哥 | 来源:发表于2020-07-03 14:15 被阅读0次

    由于多个业务需要,在一个界面会有多个弹框的存在,而这多个弹框需要按顺序、优先级给统一管理起来,不然会杂乱无章的弹出,用户会一脸懵逼啊。
    我写了一个管理器,把弹框的出现和消失给管理起来,出现和消失的时机给管理起来。
    AlertManager不关心怎么显示和消失,也就是不关系的UI层面,只管理显示和消失两个block事件。

    实现的功能:
    • 统一管理弹框
    • 弹框叠加显现
    • 弹框依次显现
    • 弹框的优先级排序
    • 弹框被拦截缓存起来;允许激活会在别的弹框消失后显示
    缺点:
    • 未能统一弹框标识,还需传入type标识参数。

    头文件

    @interface AlertManager : NSObject
    
    + (instancetype)shareManager;
    
    /// 是否根据优先级排序 默认YES
    @property (nonatomic,assign,readonly) BOOL isSortByPriority;
    
    ///被遮挡后的弹框先隐藏 默认是YES显示
    @property (nonatomic,assign,readonly) BOOL isDisplayAfterCover;
    
    /// 弹框展示
    /// @param type 弹框标识
    /// @param config 配置
    /// @param showBlock 显示回调
    /// @param dismissBlock 隐藏回调
    - (void)alertShowWithType:(NSString *)type config:(AlertConfig *)config show:(Block)showBlock dismiss:(Block)dismissBlock;
    
    - (void)alertDissMissWithType:(NSString *)type;
    
    - (void)removeWithType:(NSString *)type;
    
    /// 清楚缓存
    - (void)clearCache;
    
    @end
    

    管理器添加弹框代码

    - (void)alertShowWithType:(NSString *)type
                       config:(AlertConfig *)config
                         show:(nonnull Block)showBlock
                      dismiss:(nonnull Block)dismissBlock{
        
        //排查是否重复添加
        NSArray * keys = self.alertCache.allKeys;
        if ([keys containsObject:type]) {
            showBlock(NO,@"type标识重复");
            NSLog(@"type(%@)标识重复",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,@"本次被隐藏了啊");
                   }
               }
        }
        
        showBlock(YES,@"");
    }
    

    弹框消失的代码

    - (void)alertDissMissWithType:(NSString *)type{
        
        
        AlertConfig *config = [self.alertCache objectForKey:type];
        Block  dismissBlock = config.dismissBlock;
        dismissBlock(YES,@"");
        
        //延迟释放其他block
        ZJSemaphoreCreate
        ZJSemaphoreWait
        [self.alertCache removeObjectForKey:type];
        ZJSemaphoreSignal
        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(), ^{
                        
                        showBlock(YES,@"");
                    });
                    break;
                }
            }
        }
    }
    

    欢迎大家使用和体验啊!
    代码地址:https://github.com/zhengju/iOSDemos/tree/master/SpringBox

    相关文章

      网友评论

        本文标题:iOS弹框统一管理器

        本文链接:https://www.haomeiwen.com/subject/bzhrqktx.html