// // JXTAlertController.h // JXTAlertManager // // Created by JXT on 2016/12/22. // Copyright © 2016年 JXT. All rights reserved. // #import NS_ASSUME_NONNULL_BEGIN #pragma mark - I.JXTAlertController构造 @class JXTAlertController; /** JXTAlertController: alertAction配置链 @param title 标题 @return JXTAlertController对象 */ typedef JXTAlertController * _Nonnull (^JXTAlertActionTitle)(NSString *title); /** JXTAlertController: alert按钮执行回调 @param buttonIndex 按钮index(根据添加action的顺序) @param action UIAlertAction对象 @param alertSelf 本类对象 */ typedef void (^JXTAlertActionBlock)(NSInteger buttonIndex, UIAlertAction *action, JXTAlertController *alertSelf); /** JXTAlertController 简介: 1.针对系统UIAlertController封装,支持iOS8及以上 2.关于iOS9之后的`preferredAction`属性用法: `alertController.preferredAction = alertController.actions[0];` 效果为将已存在的某个action字体加粗,原cancel样式的加粗字体成为deafult样式,cancel样式的action仍然排列在最下 总体意义不大,且仅限于`UIAlertControllerStyleAlert`,actionSheet无效,功能略微鸡肋,不再单独封装 3.关于`addTextFieldWithConfigurationHandler:`方法: 该方法同样仅限于`UIAlertControllerStyleAlert`使用,使用场景较为局限,推荐直接调用,不再针对封装 4.关于自定义按钮字体或者颜色,可以利用kvc间接访问这些私有属性,但是不推荐 `[alertAction setValue:[UIColor grayColor] forKey:@"titleTextColor"]` */ NS_CLASS_AVAILABLE_IOS(8_0) @interface JXTAlertController : UIAlertController /** JXTAlertController: 禁用alert弹出动画,默认执行系统的默认弹出动画 */ - (void)alertAnimateDisabled; /** JXTAlertController: alert弹出后,可配置的回调 */ @property (nullable, nonatomic, copy) void (^alertDidShown)(void); /** JXTAlertController: alert关闭后,可配置的回调 */ @property (nullable, nonatomic, copy) void (^alertDidDismiss)(void); /** JXTAlertController: 设置toast模式展示时间:如果alert未添加任何按钮,将会以toast样式展示,这里设置展示时间,默认1s */ @property (nonatomic, assign) NSTimeInterval toastStyleDuration; //deafult jxt_alertShowDurationDefault = 1s /** JXTAlertController: 链式构造alert视图按钮,添加一个alertAction按钮,默认样式,参数为标题 @return JXTAlertController对象 */ - (JXTAlertActionTitle)addActionDefaultTitle; /** JXTAlertController: 链式构造alert视图按钮,添加一个alertAction按钮,取消样式,参数为标题(warning:一个alert该样式只能添加一次!!!) @return JXTAlertController对象 */ - (JXTAlertActionTitle)addActionCancelTitle; /** JXTAlertController: 链式构造alert视图按钮,添加一个alertAction按钮,警告样式,参数为标题 @return JXTAlertController对象 */ - (JXTAlertActionTitle)addActionDestructiveTitle; @end #pragma mark - II.UIViewController扩展使用JXTAlertController /** JXTAlertController: alert构造块 @param alertMaker JXTAlertController配置对象 */ typedef void(^JXTAlertAppearanceProcess)(JXTAlertController *alertMaker); @interface UIViewController (JXTAlertController) /** JXTAlertController: show-alert(iOS8) @param title title @param message message @param appearanceProcess alert配置过程 @param actionBlock alert点击响应回调 */ - (void)jxt_showAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message appearanceProcess:(JXTAlertAppearanceProcess)appearanceProcess actionsBlock:(nullable JXTAlertActionBlock)actionBlock NS_AVAILABLE_IOS(8_0); /** JXTAlertController: show-actionSheet(iOS8) @param title title @param message message @param appearanceProcess actionSheet配置过程 @param actionBlock actionSheet点击响应回调 */ - (void)jxt_showActionSheetWithTitle:(nullable NSString *)title message:(nullable NSString *)message appearanceProcess:(JXTAlertAppearanceProcess)appearanceProcess actionsBlock:(nullable JXTAlertActionBlock)actionBlock NS_AVAILABLE_IOS(8_0); @end @interface UIAlertController (LMJ) /** JXTAlertController: show-alert(iOS8) @param title title @param message message @param appearanceProcess alert配置过程 @param actionBlock alert点击响应回调 */ + (void)mj_showAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message appearanceProcess:(JXTAlertAppearanceProcess)appearanceProcess actionsBlock:(nullable JXTAlertActionBlock)actionBlock NS_AVAILABLE_IOS(8_0); /** JXTAlertController: show-actionSheet(iOS8) @param title title @param message message @param appearanceProcess actionSheet配置过程 @param actionBlock actionSheet点击响应回调 */ + (void)mj_showActionSheetWithTitle:(nullable NSString *)title message:(nullable NSString *)message appearanceProcess:(JXTAlertAppearanceProcess)appearanceProcess actionsBlock:(nullable JXTAlertActionBlock)actionBlock NS_AVAILABLE_IOS(8_0); @end NS_ASSUME_NONNULL_END /* // // ShowViewController.m // JXTAlertManagerDemo // // Created by JXT on 2016/12/21. // Copyright © 2016年 JXT. All rights reserved. // #import "ShowViewController.h" #import "JXTAlertManagerHeader.h" static NSString *const cellId = @"CELLID"; @interface ShowViewController () @property (nonatomic, strong) UITableView * tableView; @property (nonatomic, strong) NSArray * sectionViewArray; @property (nonatomic, strong) NSArray * dataArray; @end @implementation ShowViewController #pragma mark - LifeCycle - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"JXTAlertManager"; self.dataArray = @[ @[ @"1.1.常规两个按钮alert", @"1.2.简易调试使用alert,单按钮,标题默认为“确定”", @"1.3.不定数量按钮alert", @"1.4.无按钮toast样式", @"1.5.单文字HUD", @"1.6.带indicatorView的HUD", @"1.7.带进度条的HUD,成功!", @"1.8.带进度条的HUD,失败!", ], @[ @"2.1.常规alertController-Alert", @"2.2.常规alertController-ActionSheet", @"2.3.无按钮alert-toast", @"2.4.无按钮actionSheet-toast", @"2.5.带输入框的alertController-Alert", ] ]; self.sectionViewArray = @[ [self labelWithText:@"1.AlertView-推荐日常调试使用"], [self labelWithText:@"2.AlertController-iOS8"] ]; [self.view addSubview:self.tableView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - UI - (UILabel *)labelWithText:(NSString *)text { UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 20)]; label.text = text; label.font = [UIFont boldSystemFontOfSize:20]; label.backgroundColor = [[self randomColor] colorWithAlphaComponent:0.5]; label.textAlignment = NSTextAlignmentCenter; return label; } - (UITableView *)tableView { if (!_tableView) { if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) { self.automaticallyAdjustsScrollViewInsets = NO; } _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; _tableView.delegate = self; _tableView.dataSource = self; _tableView.backgroundColor = [UIColor whiteColor]; _tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); _tableView.scrollIndicatorInsets = UIEdgeInsetsMake(64, 0, 0, 0); } return _tableView; } #pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.dataArray.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSArray *sectionArray = self.dataArray[section]; return sectionArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellId]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; } cell.backgroundColor = [self randomColor]; cell.textLabel.text = self.dataArray[indexPath.section][indexPath.row]; cell.textLabel.numberOfLines = 0; return cell; } //- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section //{ // return @"title"; //} #pragma mark - UITableViewDelegate - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 70; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 25; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return 0.01; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { return self.sectionViewArray[section]; } #pragma mark alert使用示例 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; if (indexPath.section == 0) { if (indexPath.row == 0) { //1. // [JXTAlertView showAlertViewWithTitle:@"title" message:@"message" cancelButtonTitle:@"cancel" otherButtonTitle:@"other" cancelButtonBlock:^(NSInteger buttonIndex) { // NSLog(@"cancel"); // } otherButtonBlock:^(NSInteger buttonIndex) { // NSLog(@"other"); // }]; //2. jxt_showAlertTwoButton(@"常规两个按钮alert", @"支持按钮点击回调,支持C函数快速调用", @"cancel", ^(NSInteger buttonIndex) { NSLog(@"cancel"); }, @"other", ^(NSInteger buttonIndex) { NSLog(@"other"); }); } else if (indexPath.row == 1) { jxt_showAlertTitle(@"简易调试使用alert,单按钮,标题默认为“确定”"); } else if (indexPath.row == 2) { [JXTAlertView showAlertViewWithTitle:@"不定数量按钮alert" message:@"支持按钮点击回调,根据按钮index区分响应,有cancel按钮时,cancel的index默认0,无cancel时,按钮index根据添加顺序计算" cancelButtonTitle:@"cancel" buttonIndexBlock:^(NSInteger buttonIndex) { if (buttonIndex == 0) { NSLog(@"cancel"); } else if (buttonIndex == 1) { NSLog(@"按钮1"); } else if (buttonIndex == 2) { NSLog(@"按钮2"); } else if (buttonIndex == 3) { NSLog(@"按钮3"); } else if (buttonIndex == 4) { NSLog(@"按钮4"); } else if (buttonIndex == 5) { NSLog(@"按钮5"); } } otherButtonTitles:@"按钮1", @"按钮2", @"按钮3", @"按钮4", @"按钮5", nil]; } else if (indexPath.row == 3) { //1. [JXTAlertView showToastViewWithTitle:@"无按钮toast样式" message:@"可自定义展示延时时间,支持关闭回调" duration:2 dismissCompletion:^(NSInteger buttonIndex) { NSLog(@"关闭"); }]; //2. // jxt_showToastTitleDismiss(@"无按钮toast样式", 2, ^(NSInteger buttonIndex) { // NSLog(@"关闭"); // }); //3. // jxt_showToastMessage(@"无按钮toast样式", 0); } else if (indexPath.row == 4) { //1. // jxt_showTextHUDTitle(@"单文字HUD"); //2. jxt_showTextHUDTitleMessage(@"单文字HUD", @"支持子标题,手动执行关闭,可改变显示状态"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ jxt_dismissHUD(); }); } else if (indexPath.row == 5) { jxt_showLoadingHUDTitleMessage(@"带indicatorView的HUD", @"支持子标题,手动执行关闭,可改变显示状态"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ jxt_dismissHUD(); }); } else if (indexPath.row == 6) { jxt_showProgressHUDTitleMessage(@"带进度条的HUD", @"支持子标题,手动执行关闭,可改变显示状态"); __block float count = 0; #warning timer block ios10 only [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) { count += 0.05; jxt_setHUDProgress(count); if (count > 1) { [timer invalidate]; jxt_setHUDSuccessTitle(@"加载成功!"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ jxt_dismissHUD(); }); } }]; } else if (indexPath.row == 7) { jxt_showProgressHUDTitleMessage(@"带进度条的HUD", @"支持子标题,手动执行关闭,可改变显示状态"); __block float count = 0; #warning timer block ios10 only [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) { count += 0.05; jxt_setHUDProgress(count); if (count > 1) { [timer invalidate]; jxt_setHUDFailMessage(@"加载失败!"); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ jxt_dismissHUD(); }); } }]; } } else if (indexPath.section == 1) { if (indexPath.row == 0) { [self jxt_showAlertWithTitle:@"常规alertController-Alert" message:@"基于系统UIAlertController封装,按钮以链式语法模式快捷添加,可根据按钮index区分响应,可根据action区分响应,支持配置弹出、关闭回调,可关闭弹出动画" appearanceProcess:^(JXTAlertController * _Nonnull alertMaker) { alertMaker. addActionCancelTitle(@"cancel"). addActionDestructiveTitle(@"按钮1"); } actionsBlock:^(NSInteger buttonIndex, UIAlertAction * _Nonnull action, JXTAlertController * _Nonnull alertSelf) { if (buttonIndex == 0) { NSLog(@"cancel"); } else if (buttonIndex == 1) { NSLog(@"按钮1"); } NSLog(@"%@--%@", action.title, action); }]; } else if (indexPath.row == 1) { [self jxt_showActionSheetWithTitle:@"常规alertController-ActionSheet" message:@"基于系统UIAlertController封装,按钮以链式语法模式快捷添加,可根据按钮index区分响应,可根据action区分响应,支持配置弹出、关闭回调,可关闭弹出动画" appearanceProcess:^(JXTAlertController * _Nonnull alertMaker) { alertMaker. addActionCancelTitle(@"cancel"). addActionDestructiveTitle(@"按钮1"). addActionDefaultTitle(@"按钮2"). addActionDefaultTitle(@"按钮3"). addActionDestructiveTitle(@"按钮4"); } actionsBlock:^(NSInteger buttonIndex, UIAlertAction * _Nonnull action, JXTAlertController * _Nonnull alertSelf) { if ([action.title isEqualToString:@"cancel"]) { NSLog(@"cancel"); } else if ([action.title isEqualToString:@"按钮1"]) { NSLog(@"按钮1"); } else if ([action.title isEqualToString:@"按钮2"]) { NSLog(@"按钮2"); } else if ([action.title isEqualToString:@"按钮3"]) { NSLog(@"按钮3"); } else if ([action.title isEqualToString:@"按钮4"]) { NSLog(@"按钮4"); } }]; } else if (indexPath.row == 2) { [self jxt_showAlertWithTitle:@"无按钮alert-toast" message:@"toast样式,可自定义展示延时时间,支持配置弹出、关闭回调,可关闭弹出动画" appearanceProcess:^(JXTAlertController * _Nonnull alertMaker) { alertMaker.toastStyleDuration = 2; [alertMaker setAlertDidShown:^{ [self logMsg:@"alertDidShown"];//不用担心循环引用 }]; alertMaker.alertDidDismiss = ^{ [self logMsg:@"alertDidDismiss"]; }; } actionsBlock:NULL]; } else if (indexPath.row == 3) { [self jxt_showActionSheetWithTitle:@"无按钮actionSheet-toast" message:@"toast样式,可自定义展示延时时间,支持配置弹出、关闭回调,可关闭弹出动画" appearanceProcess:^(JXTAlertController * _Nonnull alertMaker) { alertMaker.toastStyleDuration = 3; //关闭动画效果 [alertMaker alertAnimateDisabled]; [alertMaker setAlertDidShown:^{ NSLog(@"alertDidShown"); }]; alertMaker.alertDidDismiss = ^{ NSLog(@"alertDidDismiss"); }; } actionsBlock:NULL]; } else if (indexPath.row == 4) { [self jxt_showAlertWithTitle:@"带输入框的alertController-Alert" message:@"点击按钮,控制台打印对应输入框的内容" appearanceProcess:^(JXTAlertController * _Nonnull alertMaker) { alertMaker. addActionDestructiveTitle(@"获取输入框1"). addActionDestructiveTitle(@"获取输入框2"); [alertMaker addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.placeholder = @"输入框1-请输入"; }]; [alertMaker addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.placeholder = @"输入框2-请输入"; }]; } actionsBlock:^(NSInteger buttonIndex, UIAlertAction * _Nonnull action, JXTAlertController * _Nonnull alertSelf) { if (buttonIndex == 0) { UITextField *textField = alertSelf.textFields.firstObject; [self logMsg:textField.text];//不用担心循环引用 } else if (buttonIndex == 1) { UITextField *textField = alertSelf.textFields.lastObject; [self logMsg:textField.text]; } }]; } } } #pragma mark - Methods - (void)logMsg:(NSString *)msg { NSLog(@"%@", msg); } - (UIColor *)randomColor { CGFloat r = arc4random_uniform(255); CGFloat g = arc4random_uniform(255); CGFloat b = arc4random_uniform(255); return [UIColor colorWithRed:(r / 255.0) green:(g / 255.0) blue:(b / 255.0) alpha:0.3f]; } @end */