UIAlertView/UIAlertController封装使用
基于UIAlertView封装的JXTAlertView,这个是将之前写Demo时搞的一套快捷使用alertView的工具抽离整理出来的,并提供了C函数直接调用,像这样:
jxt_showAlertTitle(@"简易调试使用alert,单按钮,标题默认为“确定”");
就可以直接显示出一个alertView。
基于UIAlertController封装的JXTAlertController,支持iOS8及以上。调用方式为UIViewController的扩展分类方法,支持使用链式语法的方式配置alert的按钮及样式,相对于变参或者数组,更加简洁。
https://github.com/kukumaluCN/JXTAlertManager
1. JXTAlertView 便捷调试工具
之所以叫做快捷调试工具,就是因为这套代码是之前写Demo时搞出来的。所以,如果不是要适配iOS7及以下版本的话,这套代码还是建议只用在平时Demo测试。也因此,并没有针对UIActionSheet再进行封装,说白了是因为懒……
平时写一些Demo代码时,总会用到alert、toast、HUD这些工具,如果没有一套简便的工具,会麻烦很多,所以便从轻量便捷角度出发,基于UIAlertView,封装实现了alert、toast、HUD这些常用工具。
1.1.快捷使用alertView
如果只是简单的一个提示,可以这样使用(这里只是一个示例,详细用法见源码):
jxt_showAlertTitle(@"简易调试使用alert,单按钮,标题默认为“确定”");
其实现是基于:
[JXTAlertView showAlertViewWithTitle:title
message:message
cancelButtonTitle:cancelButtonTitle
otherButtonTitle:otherButtonTitle
cancelButtonBlock:cancelBlock
otherButtonBlock:otherBlock];
这是常用的两个以内的按钮的alertView,也可以这样使用:
jxt_showAlertTwoButton(@"title", @"message", @"cancel", ^(NSInteger buttonIndex) {
NSLog(@"cancel");
}, @"other", ^(NSInteger buttonIndex) {
NSLog(@"other");
});
针对于复杂的多按钮的alertView,还是使用变参方式,按钮响应,根据添加的按钮标题的index号依序区分:
[JXTAlertView showAlertViewWithTitle:@"title"
message:@"message"
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];
1.2.简单的toast
这里的toast提示,有别于传统意义上的toast,因为其是基于alertView实现的,是一个没有按钮的alertView。可自定义展示延时时间,支持关闭回调的配置。
[JXTAlertView showToastViewWithTitle:@"title"
message:@"message"
duration:2
dismissCompletion:^(NSInteger buttonIndex) {
NSLog(@"关闭");
}];
1.3.三种HUD的实现
这里的HUD区别于toast之处在于,其关闭时机可控,并不是单纯的一个延时展示。
三种HUD是指单纯的文字型、带风火轮(菊花)的加载窗、带进度条的加载窗。
后两者用KVC的方式访问了alertView的私有属性accessoryView实现,这样做可能没有太大问题,不过还是不建议线上开发使用,而且利用这种方式访问私有属性本来就是不太安全的,一旦key(私有属性名)改变了,不做容错处理,会崩溃,源码实现中做了一定的容错,但是,一旦对应key变化,也就导致对应功能失效了。
示例代码(C函数方式):
jxt_showLoadingHUDTitleMessage(@"title", @"message");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
jxt_dismissHUD();
});
HUD还有对应的简易的显示加载成功失败状态的方法,以及刷新进度条进度值的方法,详情见Demo。
2. JXTAlertController(iOS8)(链式语法的“隐患”)
JXTAlertController是基于系统的UIAlertController封装的,因此也只能支持iOS8及以上系统版本。
虽然源码中的JXTAlertManagerHeader.h做了一个版本适配,但是,其意义更多在于提示,很可能因此出错,所以,如果要适配iOS7,对应方法还是需要自行适配。
下面都以alert举例,actionSheet同理。
2.1.结构说明
/**
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);
上述方法是针对UIViewController做的分类扩展,详见源码。
也就是在某个VC中使用时,可直接用self指针调用。
JXTAlertAppearanceProcess是配置块,JXTAlertActionBlock是按钮响应回调块。
2.2.链式语法添加按钮
[self jxt_showActionSheetWithTitle:@"title"
message:@"message"
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");
}
}];
appearanceProcess配置块中,alertMaker是当前alertController对象,addActionCancelTitle(@"cancel")是添加一个按钮,其等效于:
[alertController addAction:[UIAlertAction actionWithTitle:@"cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *_Nonnull action) {
}]];
这里引入了简单的链式语法,可以连续添加系统支持的三类action按钮,当然UIAlertActionStyleCancel这个样式的action只能添加一次。这样可以大大简化代码。
actionsBlock是action按钮响应回调,可以根据index区分响应,index根据执行add的语法链从0依序增加,cancel类型的action布局位置是固定的,和添加顺序无关,但其index与添加顺序有关。
对于复杂或者特殊的alertController,也可以根据action.title或者action区分响应。
2.3.链式语法的“隐患”
用过Masonry这个库的,应该都对链式语法不会太陌生。链式语法可以使得代码简化且逻辑清晰化。但是,其也有一定的“隐患”存在。
Masonry应该是用的最多的一个自动布局的三方库,类似的还有SDAutoLayout(这里只是举例,同样的三方还有很多,这个应该是除了Masonry外,用的相对多一些的一个)这样的,同样的链式语法,后者似乎更加简洁优雅。那为什么大名鼎鼎的Masonry不这么干呢?我想是因为“安全”。
用SDAutoLayout的Demo做一个实验:
view为nil导致的崩溃
这里把view0置为nil,之后运行,程序直接崩溃了。。。这类似于执行一个未赋值的空block。
有人可能会认为这样的实验没有意义,为nil了干嘛还要布局呢?其实这是笔者前阵子在封装一个链式库时遇到的问题:实际应用开发中,情况要复杂很多,有些view是动态添加的,甚至是根据接口数据动态创建的,如果在处理这类代码逻辑中稍有不慎,就会造成上述问题,给不存在的view进行布局,直接导致程序崩溃。。。
其实这也是代码书写规范的问题,针对这类动态view,在处理时,本就应该添加if条件判断的,不过有时容易忽视,或者他人接手相关代码时,也容易忽略。如果用Masonry的块配置布局,就不会发生这类问题,因为这种情况,对于Masonry那种写法,就是一个空指针执行一个方法,其结果就是不执行,而像SDAutoLayout这类的,不作判空处理,就会导致程序崩溃。这里尤其要注意。
2.4.其他配置
针对alert上的输入框,保持系统的添加方式,示例如下:
[self jxt_showAlertWithTitle:@"title"
message:@"message"
appearanceProcess:^(JXTAlertController * _Nonnull alertMaker) {
alertMaker.
addActionDestructiveTitle(@"获取输入框1").
addActionDestructiveTitle(@"获取输入框2");
[alertMaker setAlertDidShown:^{
[self logMsg:@"alertDidShown"];//不用担心循环引用
}];
alertMaker.alertDidDismiss = ^{
[self logMsg:@"alertDidDismiss"];
};
[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];
}
}];
对于alert展示和关闭的回调,同样支持以block的方式配置。
如果appearanceProcess块不进行任何配置操作,即无按钮的alert,同样默认以toast模式处理。可通过设置toastStyleDuration属性,配置toast展示延迟时间。
2.5.改变alertController的字体颜色
可以通过KVC的方式访问alertController的私有属性,从而进行修改对应的字体的颜色,甚至字体。
对于UIAlertAction,可以用下面的方式修改字体颜色:
[alertAction setValue:[UIColor grayColor] forKey:@"titleTextColor"];
修改UIAlertAction字体颜色的效果
但是就像前面说的,个人并不推荐这类方式,所以源码中没有提供相关的方法。
如果有对应的特殊需求,总体来说,还是自定义alert视图比较灵活,网上相关的开源库也有很多可以直接使用,不必总是纠结于系统的实现方式。
最后,欢迎使用JXTAlertManager,如果遇到任何问题,请及时联系作者。
参考文章:(链接可到原文查看)
1.iOS更改UIActionController弹出字体的样式
2.UIAlertController 简单修改title以及按钮的字体颜色
3.How to add subview inside UIAlertView for iOS 7?
4.UIAlertView addSubview in iOS7
5.iOS UIAlertView中UIActivityindicatorView风火轮提示加载等待
UIAlertView/UIAlertController封装使用的更多相关文章
- oc UIAlertController封装
#define SHOWALERT(MESSAGE) \ UIAlertController *alertController = [UIAlertController alertController ...
- iOS (封装)一句话调用系统的alertView和alertController
前言: 本文仅作参考存留,请用新版封装:iOS 更加优雅便捷的UIAlertView/UIAlertController封装使用 UIAlertController是iOS8.0之后出来的新方法,其将 ...
- iOS8以后UIAlertView和UIActionSheet两种alert页面都将通过UIAlertController来创建
1. Important: UIAlertView is deprecated in iOS 8. (Note that UIAlertViewDelegate is also deprecated. ...
- 个性化 UIAlertController
系统的 UIAlertController 封装的很漂亮,用block代替之前 UIAlertView 的代理,用起来更方便的,但是其曝露出来的接口也不多如果要个性化一些东西,比如字体大小.颜色就不是 ...
- iOS8新特性(1)——UIAlertController
一.iOS8介绍 iOS8 新特性,主要是UI上进行了统一 1.UIAlertController 2.UIPresentaionController:管理所有通过modal出来的控制器(看笔记) 3 ...
- iOS 8及以后版本 如何创建UIAlertView?
1. Important: UIAlertView is deprecated in iOS 8. (Note that UIAlertViewDelegate is also deprecated. ...
- UIAlertController custom font, size, color
本文转载至 http://stackoverflow.com/questions/26460706/uialertcontroller-custom-font-size-color up vote2d ...
- iOS开发系统类功能划分
0.OC语法基础 CHOCBase Object C语法学习笔记(一) Object C语法学习笔记(二) 1.UI类 自定义控件程序运行流程 setNeedsLayOut和setNeedsDispl ...
- CHUI类
自定义控件程序运行流程 setNeedsLayOut和setNeedsDisplay区别 masonry使用技巧 1.普通展示 UILabel UIView UI控件的位置 U ...
随机推荐
- java.sql.SQLException: ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
问题来源:我在执行sql生成json并存入数据库是报的错. 原因:存json的字段我定义其类型为varchar2. 分析:这个异常是指,用户向数据库执行插入数据操作时,某条数据的某个字段值过长,如果是 ...
- [Python爬虫] :Selenium +phantomjs 利用 pyquery抓取脚本链接对应的内容
抓取上面对应链接的网页的文章的内容 ele = element.attr("onclick") self.driver.execute_script(ele) sub_seleni ...
- angularJs中$controller的使用
$controller的使用 参考:https://stackoverflow.com/questions/27866620/can-someone-provide-a-use-case-for-th ...
- (转)Debug Assertion Failed! Expression: _pFirstBlock == pHead
最近在VS上开发C++程序时遇到了这个错误: Debug Assertion Failed! Expression:_pFirstBlock == pHead 如图: 点击Abort之后,查看调用 ...
- 给ajax表单提交数据前面加上实体名称
有时候我们后台做了一个引用类型例如: 下面的实体以C#为例 public class Order{ public string orderId{get;set;} public OrderItem o ...
- mysql生成不重复随机数(unique number generation)
转自:http://blog.csdn.net/dreamer2020/article/details/52049629 问题来源 业务中有时会遇到要生成不重复随机数的情况,例如,新生成一个商品编号. ...
- JAVA基础编程50题(4-6题)具体解释
一.描写叙述 1.将一个正整数分解质因数.比如:输入90,打印出90=2*3*3*5. 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完毕: (1)假设这个质数恰等于n,则说明 ...
- java parse 带英文单词的日期字符串 转 date (转化新浪微博api返回的时间)
拂晓风起 专注前端技术cocos2d.js.flash.html5,联系:kenkofox@qq.com.如果读者要找腾讯工作机会,请不吝推荐简历. 博客园 首页 新闻 新随笔 联系 管理 订阅 随笔 ...
- springcloud报错Cannot execute request on any known server
启动springcloud服务中心,提示这个错误:Cannot execute request on any known server 网上一般说是修改application.properties配置 ...
- springboot升级到2.0后context-path配置不起作用
springboot升级到2.0后,context-path配置不起作用,改成了: server.servlet.context-path=/projname