// // YMAlert.m // yuemoClient // // Created by YoMi on 2023/11/6. // #import "YMAlert.h" @interface YMPopupConfig : NSObject #pragma mark - 基础属性 /// 代理 支持多代理 @property (nonatomic , strong) NSHashTable * delegate; /// 标识 默认为空 @property (nonatomic , strong) NSString * identifier; /// 弹窗容器 @property (nonatomic , weak ) UIView * parentView; /// 自定义view @property (nonatomic , weak ) UIView * currCustomView; /// 弹窗位置 默认YMPositionStyleCenter @property (nonatomic , assign) YMPositionStyle positionStyle; /// 显示时动画弹窗样式 默认YMPopupStyleFade @property (nonatomic , assign) YMPopupStyle popStyle; /// 移除时动画弹窗样式 默认YMDismissStyleFade @property (nonatomic , assign) YMDismissStyle dismissStyle; /// 显示时动画时长,> 0。不设置则使用默认的动画时长 设置成YMPopupStyleNO, 该属性无效 @property (nonatomic , assign) NSTimeInterval popDuration; /// 隐藏时动画时长,>0。不设置则使用默认的动画时长 设置成YMDismissStyleNO, 该属性无效 @property (nonatomic , assign) NSTimeInterval dismissDuration; /// 弹窗水平方向(X)偏移量校准 默认0 @property (nonatomic , assign) CGFloat adjustX; /// 弹窗垂直方向(Y)偏移量校准 默认0 @property (nonatomic , assign) CGFloat adjustY; /// 背景颜色 默认rgb(0,0,0) 透明度0.3 @property (nonatomic , strong) UIColor * bgColor; /// 显示时背景的透明度,取值(0.0~1.0),默认为0.3 @property (nonatomic , assign) CGFloat bgAlpha; /// 是否隐藏背景 默认NO @property (nonatomic , assign) BOOL isHideBg; /// 显示时点击背景是否移除弹窗,默认为NO。 @property (nonatomic , assign) BOOL isClickBgDismiss; /// 是否监听屏幕旋转,默认为YES @property (nonatomic , assign) BOOL isObserverScreenRotation; /// 是否支持点击回馈 默认NO (暂时关闭) @property (nonatomic , assign) BOOL isClickFeedback; /// 是否规避键盘 默认YES @property (nonatomic , assign) BOOL isAvoidKeyboard; /// 弹窗和键盘的距离 默认10 @property (nonatomic , assign) CGFloat avoidKeyboardSpace; /// 显示多长时间 默认0 不会消失 @property (nonatomic , assign) NSTimeInterval showTime; /// 自定view圆角方向设置 默认UIRectCornerAllCorners 当cornerRadius>0时生效 @property (nonatomic , assign) UIRectCorner rectCorners; /// 自定义view圆角大小, 默认 0 @property (nonatomic , assign) CGFloat cornerRadius; /// 弹出震动反馈 默认NO iOS10+ 系统才有此效果 @property (nonatomic , assign) BOOL isImpactFeedback; #pragma mark - 群组相关属性 /// 群组标识 统一给弹窗编队 方便独立管理 默认为nil,统一全局处理 @property (nonatomic , strong) NSString * groupId; /// 是否堆叠 默认NO 如果是YES priority优先级不生效 @property (nonatomic , assign) BOOL isStack; /// 单显示 默认NO 只会显示优先级最高的popView @property (nonatomic , assign) BOOL isSingle; /// 优先级 范围0~1000 (默认0,遵循先进先出) isStack和isSingle为NO的时候生效 @property (nonatomic , assign) CGFloat priority; #pragma mark - 拖拽手势相关属性 /// 拖拽方向 默认 不可拖拽 @property (nonatomic , assign) YMDragStyle dragStyle; /// X轴或者Y轴拖拽移除临界距离 范围(0 ~ +∞) 默认0 不拖拽移除 基使用于dragStyle @property (nonatomic , assign) CGFloat dragDistance; /// 拖拽移除动画类型 默认同dismissStyle @property (nonatomic , assign) YMDismissStyle dragDismissStyle; /// 拖拽消失动画时间 默认同 dismissDuration @property (nonatomic , assign) NSTimeInterval dragDismissDuration; /// 拖拽复原动画时间 默认0.25s @property (nonatomic , assign) NSTimeInterval dragReboundTime; /// 轻扫方向 默认 不可轻扫 前提开启dragStyle @property (nonatomic , assign) YMSweepStyle sweepStyle; /// 轻扫速率 控制轻扫移除 默认1000 基于使用sweepStyle @property (nonatomic , assign) CGFloat swipeVelocity; /// 轻扫移除的动画 默认YMSweepDismissStyleVelocity @property (nonatomic , assign) YMSweepDismissStyle sweepDismissStyle; #pragma mark - 交互回调 /// 点击背景 @property (nonatomic , copy ) YmVoidBlock bgClickBlock; /// 长按背景 @property (nonatomic , copy ) YmVoidBlock bgLongPressBlock; /// 弹窗pan手势偏移量 @property (nonatomic , copy ) YmPointBlock panOffsetBlock; #pragma mark - 以下键盘弹出/收起 第三方键盘会多次回调(百度,搜狗测试得出), 原生键盘回调一次 /// 键盘将要弹出 @property (nonatomic , copy ) YmVoidBlock keyboardWillShowBlock; /// 键盘弹出完毕 @property (nonatomic , copy ) YmVoidBlock keyboardDidShowBlock; /// 键盘frame将要改变 @property (nonatomic , copy ) YmKeyBoardChangeBlock keyboardFrameWillChangeBlock; /// 键盘frame改变完毕 @property (nonatomic , copy ) YmKeyBoardChangeBlock keyboardFrameDidChangeBlock; /// 键盘将要收起 @property (nonatomic , copy ) YmVoidBlock keyboardWillHideBlock; /// 键盘收起完毕 @property (nonatomic , copy ) YmVoidBlock keyboardDidHideBlock; #pragma mark - 生命周期回调(Block) /// 将要显示 回调 @property (nonatomic , copy ) YmVoidBlock popViewWillPopBlock; /// 已经显示完毕 回调 @property (nonatomic , copy ) YmVoidBlock popViewDidPopBlock; /// 将要开始移除 回调 @property (nonatomic , copy ) YmVoidBlock popViewWillDismissBlock; /// 已经移除完毕 回调 @property (nonatomic , strong) NSHashTable * popViewDidDismissBlocks; /// 倒计时 回调 @property (nonatomic , copy ) YmAlertCountDownBlock popViewCountDownBlock; @end @implementation YMPopupConfig - (instancetype)init { self = [super init]; if (self) { [self initDefaultData]; } return self; } - (void)initDefaultData { _positionStyle = YMPositionStyleCenter; _popStyle = YMPopupStyleFade; _dismissStyle = YMDismissStyleFade; _bgColor = UIColor.blackColor; _bgAlpha = 0.3; _isObserverScreenRotation = YES; _isAvoidKeyboard = YES; _avoidKeyboardSpace = 10; } - (NSHashTable *)delegate { if (_delegate) return _delegate; _delegate = [NSHashTable hashTableWithOptions:(NSPointerFunctionsWeakMemory)]; return _delegate; } - (NSHashTable *)popViewDidDismissBlocks { if (_popViewDidDismissBlocks) return _popViewDidDismissBlocks; _popViewDidDismissBlocks = [NSHashTable hashTableWithOptions:(NSPointerFunctionsWeakMemory)]; return _popViewDidDismissBlocks; } @end #pragma mark - YMAlert @interface YMAlert () @property (nonatomic , weak ) YMPopupView * popView; @property (nonatomic , strong) YMPopupConfig * config; @end @implementation YMAlert + (instancetype)alert { YMAlert *alert = YMAlert.alloc.init; return alert; } - (YMPopupConfig *)config { if (_config) return _config; _config = YMPopupConfig.alloc.init; return _config; } #define ym_property_block(class, subclass, proprety) \ - (class)proprety\ {\ return ^(subclass object) {\ self.config.proprety = object;\ return self;\ };\ } - (YMAlertDelegate)delegate { return ^(id object) { if (object) { [self.config.delegate addObject:object]; } return self; }; } ym_property_block(YMAlertString, id, identifier); ym_property_block(YMAlertView, id, parentView); - (YMAlertCustomView)currCustomView{ return ^(YmViewBlock object){ self.config.currCustomView = object(); return self; }; } ym_property_block(YMAlertPositionStyle, YMPositionStyle, positionStyle); ym_property_block(YMAlertPopStyle, YMPopupStyle, popStyle); ym_property_block(YMAlertDismissStyle, YMDismissStyle, dismissStyle); ym_property_block(YMAlertInterval, NSTimeInterval, popDuration); ym_property_block(YMAlertInterval, NSTimeInterval, dismissDuration); ym_property_block(YMAlertFloat, CGFloat, adjustX); ym_property_block(YMAlertFloat, CGFloat, adjustY); ym_property_block(YMAlertColor, id, bgColor); ym_property_block(YMAlertFloat, CGFloat, bgAlpha); ym_property_block(YMAlertBOOL, BOOL, isHideBg); ym_property_block(YMAlertBOOL, BOOL,isClickBgDismiss); ym_property_block(YMAlertBOOL, BOOL, isObserverScreenRotation); ym_property_block(YMAlertBOOL, BOOL, isClickFeedback); ym_property_block(YMAlertBOOL, BOOL, isAvoidKeyboard); ym_property_block(YMAlertFloat, CGFloat, avoidKeyboardSpace); ym_property_block(YMAlertInterval, NSTimeInterval, showTime); ym_property_block(YMAlertCorner, UIRectCorner, rectCorners); ym_property_block(YMAlertFloat, CGFloat, cornerRadius); ym_property_block(YMAlertBOOL, BOOL, isImpactFeedback); ym_property_block(YMAlertString, id, groupId); ym_property_block(YMAlertBOOL, BOOL, isStack); ym_property_block(YMAlertBOOL, BOOL, isSingle); ym_property_block(YMAlertFloat, CGFloat, priority); ym_property_block(YMAlertDragStyle, YMDragStyle, dragStyle); ym_property_block(YMAlertFloat, CGFloat, dragDistance); ym_property_block(YMAlertDismissStyle, YMDismissStyle, dragDismissStyle); ym_property_block(YMAlertInterval, NSTimeInterval, dragDismissDuration); ym_property_block(YMAlertSweepStyle, YMSweepStyle, sweepStyle); ym_property_block(YMAlertFloat, CGFloat, swipeVelocity); ym_property_block(YMAlertSweepDismissStyle, YMSweepDismissStyle, sweepDismissStyle); ym_property_block(YMAlertBlock, YmVoidBlock, bgClickBlock); ym_property_block(YMAlertBlock, YmVoidBlock, bgLongPressBlock); ym_property_block(YMAlertPointBlock, YmPointBlock, panOffsetBlock); ym_property_block(YMAlertBlock, YmVoidBlock, keyboardWillShowBlock); ym_property_block(YMAlertBlock, YmVoidBlock, keyboardDidShowBlock); ym_property_block(YMAlertKeyBoardChangeBlock, YmKeyBoardChangeBlock, keyboardFrameWillChangeBlock); ym_property_block(YMAlertKeyBoardChangeBlock, YmKeyBoardChangeBlock, keyboardFrameDidChangeBlock); ym_property_block(YMAlertBlock, YmVoidBlock, keyboardWillHideBlock); ym_property_block(YMAlertBlock, YmVoidBlock, keyboardDidHideBlock); ym_property_block(YMAlertBlock, YmVoidBlock, popViewWillPopBlock); ym_property_block(YMAlertBlock, YmVoidBlock, popViewDidPopBlock); ym_property_block(YMAlertBlock, YmVoidBlock, popViewWillDismissBlock); - (YMAlertBlock)popViewDidDismissBlock { return ^(YmVoidBlock object) { if (object) { [self.config.popViewDidDismissBlocks addObject:object]; } return self; }; } ym_property_block(YMAlertAlertCountDownBlock, YmAlertCountDownBlock, popViewCountDownBlock); - (YMAlertVoid)pop { return ^ { [self show]; return self; }; } - (YMAlertVoid)dismiss { return ^ { [self hide]; return self; }; } - (void)hide { [_popView dismiss]; } - (void)show { YMPopupView * popView = ({ YMPopupConfig *config = self.config; YMPopupView * object = [YMPopupView initWithCustomView:config.currCustomView parentView:config.parentView popStyle:config.popStyle dismissStyle:config.dismissStyle]; for (id de in config.delegate) { object.delegate = de; } object.identifier = config.identifier; object.positionStyle = config.positionStyle; object.popStyle = config.popStyle; object.dismissStyle = config.dismissStyle; object.popDuration = config.popDuration; object.dismissDuration = config.dismissDuration; object.adjustX = config.adjustX; object.adjustY = config.adjustY; object.bgColor = config.bgColor; object.bgAlpha = config.bgAlpha; object.isHideBg = config.isHideBg; object.isClickBgDismiss = config.isClickBgDismiss; object.isObserverScreenRotation = config.isObserverScreenRotation; object.isClickFeedback = config.isClickFeedback; object.isAvoidKeyboard = config.isAvoidKeyboard; object.avoidKeyboardSpace = config.avoidKeyboardSpace; object.showTime = config.showTime; object.rectCorners = config.rectCorners; object.cornerRadius = config.cornerRadius; object.isImpactFeedback = config.isImpactFeedback; object.groupId = config.groupId; object.isStack = config.isStack; object.isSingle = config.isSingle; object.priority = config.priority; object.dragStyle = config.dragStyle; object.dragDistance = config.dragDistance; object.dragDismissStyle = config.dragDismissStyle; object.dragDismissDuration = config.dragDismissDuration; object.dragReboundTime = config.dragReboundTime; object.sweepStyle = config.sweepStyle; object.swipeVelocity = config.swipeVelocity; object.sweepDismissStyle = config.sweepDismissStyle; object.bgClickBlock = config.bgClickBlock; object.bgLongPressBlock = config.bgLongPressBlock; object.panOffsetBlock = config.panOffsetBlock; object.keyboardWillShowBlock = config.keyboardWillShowBlock; object.keyboardDidShowBlock = config.keyboardDidShowBlock; object.keyboardFrameWillChangeBlock = config.keyboardFrameWillChangeBlock; object.keyboardFrameDidChangeBlock = config.keyboardFrameDidChangeBlock; object.keyboardWillHideBlock = config.keyboardWillHideBlock; object.keyboardDidHideBlock = config.keyboardDidHideBlock; object.popViewWillPopBlock = config.popViewWillPopBlock; object.popViewDidPopBlock = config.popViewDidPopBlock; object.popViewWillDismissBlock = config.popViewWillDismissBlock; for (YmVoidBlock block in config.popViewDidDismissBlocks) { if (block) { object.popViewDidDismissBlock = block; } } object.popViewCountDownBlock = config.popViewCountDownBlock; object; }); _popView = popView; [popView pop]; } + (NSArray *)getAllPopView { return YMPopupView.getAllPopView; } + (NSArray *)getAllPopViewForParentView:(UIView *)parentView { return [YMPopupView getAllPopViewForParentView:parentView]; } + (NSArray *)getAllPopViewForPopView:(UIView *)popView { return [YMPopupView getAllPopViewForPopView:popView]; } + (YMPopupView *)getPopViewForKey:(NSString *)key { return [YMPopupView getPopViewForKey:key]; } + (void)dismissAllAlert:(YmVoidBlock)complete { [YMPopupView removeAllPopViewComplete:complete]; } + (void)dismissAlertComplete:(YmVoidBlock)complete { [YMPopupView removeLastPopViewComplete:complete]; } + (void)dismissAlertForAlert:(YMAlert *)alert complete:(YmVoidBlock)complete { [YMPopupView removePopView:alert.popView complete:complete]; } + (void)dismissAlertForKey:(NSString *)key complete:(YmVoidBlock)complete { [YMPopupView removePopViewForKey:key complete:complete]; } + (void)dismissAlertForPopView:(YMPopupView *)popView complete:(YmVoidBlock)complete { [YMPopupView removePopView:popView complete:complete]; } @end